mysql抖动可能的原因_12 | 为什么我的MySQL会“抖”一下?

一条 SQL 语句,正常快,有时特别慢,难复现,随机持续时间短。

一、SQL语句为什么变“慢”

第 2 篇文章介绍 WAL 机制。InnoDB 更新时,只做写日志(redo log重做日志)这个磁盘操作。酒店记账粉板,更新内存写完redo log 返回给客户端,更新成功。

掌柜记忆是内存。更新账本,内存里写入磁盘 flush。flush前,赊账总额和账本记录不一致。今天赊账只在粉板。

不一致时,内存页为“脏页”。一致,为“干净页”。

原来欠 10 文,又赊 9 文。

5a9134b777c7

图 1 “孔乙己赊账”更新和flush 过程

MySQL “抖”瞬间,可能就是刷脏页(flush):将内存页写入磁盘。

二、什么情况会引发数据库 flush?

1、粉板满了,再有赊账,放下手里活儿,粉板记录擦掉一些,继续记。擦掉前记账本。redo log 写满,停止更新,checkpoint 往前推,redo log留空继续写。

5a9134b777c7

图 2 redo log 状态图

checkpoint 不是随便往前修改位置就可以。从 CP 推到 CP’,两点之间日志,所有脏页 flush 磁盘。write pos 到 CP’可再写。

2.生意太好记不住了,找账本把孔乙己这笔账先加进去。1)写binlog

内存不足,需新内存页,内存不够用,淘汰数据页。如果淘汰“脏页”,先将脏页写磁盘。2)写磁盘,空出内存

内存直接淘汰掉,下次从磁盘读入数据页,拿 redo log 出来应用不就行?性能考虑。如果刷脏页一定写盘,保证数据页两种状态:

(1)内存里存在,直接返回;

(2)内存没有数据,文件上肯定是正确,读入内存后返回(效率高)。

3.生意不忙,更新账本。MySQL“空闲”刷“脏页”。

4.年底结账。MySQL 正常关闭脏页flush 到磁盘上,下次启动直接从磁盘上读,快。

四种场景对性能影响

三、四不会太关注“性能”。

(1)redo log 满, InnoDB 尽量避免。系统不能更新,监控上看,更新数跌为 0。

(2)内存不够用,常态。InnoDB缓冲池(buffer pool)中的内存页有三种状态:

没用; 用了干净页; 用了脏页。

策略:尽量使用内存,长时间运行库,未被使用页很少。

要读入数据页没在内存,到缓冲池申请。从内存中淘汰数据页(最久不用):干净页,释放复用;脏页,刷到磁盘,变干净复用。

刷脏页也会影响性能,控制脏页比例,避免:

1. 淘汰脏页太多,响应时间明显变长;

2.  日志写满,更新堵住,写性能 0。

三、InnoDB刷脏页的控制策略

告诉 InnoDB 所在主机的IO 能力知道全力刷脏页速度

innodb_io_capacity 设置成磁盘的IOPS(用于计算机存储设备,如硬盘(HDD)、固态硬盘(SSD)或存储区域网络(SAN))性能测试的量测方式。

通过 fio工具测试磁盘随机读写命令:

fio -filename=$filename -direct=1 -iodepth 1  -thread -rw=randrw -ioengine=psync -bs=16k -size=500M -numjobs=10 -runtime=10  -group_reporting -name=mytest

没正确地设置innodb_io_capacity 参数,导致性能问题。MySQL 写慢,TPS 很低,数据库主机的IO 压力不大:

主机磁盘SSD,innodb_io_capacity=300。InnoDB 系统能力差,刷脏页比脏生成速度还慢,脏页累积,影响性能。

不能一直全力刷,还需服务用户请求。

3.1控制刷脏页速度,参考因素

刷太慢,1、脏页太多,2、redo log 写满

InnoDB 先单独算出两个数字:

1、根据当前脏页比例 M,算出0 ~100数字,计算数字伪代码:

多关注脏页比例,不要让它经常接近 75%

F1(M)

{

if M>=innodb_max_dirty_pages_pct (脏页比例上限,默认75%)then

return 100;

return 100*M/innodb_max_dirty_pages_pct;

}

2、InnoDB 每次写日志序号,跟 checkpoint 序号差 = N。根据N 算出 0 ~100 数字,公式F2(N)。算法复杂,N 越大,算出值越大。

F1(M)和F2(N)取较大值为R,innodb_io_capacity乘以R%控制刷脏页的速度。

F1、F2 通过脏页比例和redo log 写入速度算出来的两个值。

5a9134b777c7

图 3 InnoDB 刷脏页速度策略

脏页比例:nnodb_buffer_pool_pages_dirty/Innodb_buffer_pool_pages_total 得到的,命令:

mysql> select  VARIABLE_VALUE into @a from global_status where VARIABLE_NAME =  'Innodb_buffer_pool_pages_dirty';

select  VARIABLE_VALUE into @b from global_status where VARIABLE_NAME =  'Innodb_buffer_pool_pages_total';

select @a/@b;

3.2有趣的策略:

查询请求需先 flush 掉脏页,比平时慢。MySQL一个机制,让查询更慢:刷脏页时,旁边是脏页,“邻居”一起刷掉;相邻还是脏页一起刷。

innodb_flush_neighbors控制这个行为,= 1“连坐”机制,= 0 不找邻居(默认)

找“邻居”机械硬盘(随机 IOPS 几百)时代有意义,减少很机 IO。相同逻辑减少随机 IO 性能提升。

SSD 这类 IOPS 高的设备,innodb_flush_neighbors = 0。 IOPS 不是瓶颈,“只刷自己”更快。

小结

WAL 的概念(延续第 2 篇中介绍)

解释这个机制后续需要刷脏页操作和执行时机。

WAL 技术,数据库将随机写转换成顺序写,大大提升数据库性能。

内存脏页问题:脏页会被后台线程自动 flush,也由于数据页淘汰而触发 flush,刷脏页过程占用资源,可能让更新和查询语句响应时间长。介绍了控制刷脏页方法和监控方式。

思考题

内存128GB、innodb_io_capacity = 20000 大规格实例,正常建议将 redo log 设置成 4 个 1GB 的文件。

不慎将 redo log 设置成1 个 100M的文件,发生什么情况?为什么?

答:每次事务提交都写 redo log,设置小很快被写满,write pos 一直追 CP。停止所有更新,推进 checkpoint。

现象:磁盘压力很小,数据库出现间歇性性能下跌。

评论1

刷脏页对应redo log位置随机,redo log不同位置刷掉,redo log处理不是很麻烦?(合并间隙,移动位置?)

redo log优势:将磁盘随机转换成顺序写,这样不是redo log里随机读写么?

答:刷脏页过程不用动redo log文件。redo log“重放”时,数据页刷过,会识别跳过。

评论2

redo log保证ACID的D。

1.脏页保存到磁盘,checkpoint往前推

2.redo log记录undo变化,undo log buffer持久化undo log

3.innodb_flush_log_at_trx_commit=0,内存redo log持久化到磁盘

4.redo log记录change buffer改变,要把change buffer purge到idb

连change buffer的优化也没意义了

以及merge change buffer.merge也是脏页,持久化到磁盘

上述都是占用系统I/O,影响DML,操作频繁,'抖'向过冬。

select查询时间相对会更快。脏页变少,不用淘汰,直接用干净页。宕机恢复,速度快,checkpoint很接近LSN,恢复数据页相对较少

评论3

抖动现象,问题:

1)Innodb_buffer_pool_pages_total百万级别,不像人为设置,怎么来?

2)Innodb_buffer_pool_pages_dirty4万多开始flush了,脏页比例75,远达不到的,ssd磁盘,innodb_io_capacity=200,可以高。flush触发条件,内存不够,redo log 满,这个场景是哪种情况呢

回复: 1)是innodb 数据页总,过百万正常,16K一个,Bufree pool size 16G 就是100万

2)io_capacity设太小

评论4

buffer pool里维护脏页列表,假设redo log 的 checkpoint 记录LSN (日志序列号)= 10,内存中一干净页有修改LSN为12,大于 checkpoint 的LSN,写redo log同时该页也会被标记为脏页记录到脏页列表中,现内存不足,该页被淘汰刷到磁盘,LSN=12从脏页列表中移除,redo log推进checkpoint,到LSN=12log时,为干净页跳过。

评论5

redo log写满:redo log对应脏页flush,释放空间。问题:

1、脏页flush到磁盘上,接将脏页数据覆盖到对应磁盘上数据?是的

2、redo log断电重启,内存丢失,通过redo log数据恢复,redo log怎么释放空间?

重启了就从checkpoint 位置往后扫。 之前刷过盘, 不会重复应用redo log。

评论6

如何判断数据页是否在内存当中?

每页又编号。拿编号去内存看,没有,就去磁盘

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值