MySql-丁奇-学习笔记-为啥我的MySql会抖一下?(flush机制)

概念0
当内存数据页跟磁盘数据页的内容不一致的时候,这个内存页成为“脏页”。
内存数据写入磁盘后,内存和磁盘上的数据页就一致了,成为“干净页”。

当一条SQL,正常执行的时候特别快,但有的时候就会变得特别慢,这种场景是随机的,而且持续时间很短,很难复现。这时,可能就是在刷脏页(flush)。

什么时候会触发flush?

1. Redo Log写满了

这时,系统会停止所有更新操作,把redolog的checkpoint向前推,redolog留出空间可以继续写。
推进过程中的数据页都需要flush到磁盘。
MySql-丁奇-学习笔记-为啥我的MySql会抖一下?(flush机制)_第1张图片

2. 内存不足

内存中脏页太多了,就要淘汰一些数据页,如果淘汰的是“脏页”,就先将脏页写磁盘。
当redolog刷脏页的时候,会先判断这个脏页有没有被flush过,如果之前就flush了,那就不刷它了。

不通过redolog直接刷磁盘的目的是要提升效率,保证数据页只有两种状态:

  • 如果内存中存在,那么内存中就是正确的结果
  • 如果内存中不存在,那么从数据文件中读入内存的就是正确结果

3. 系统空闲

系统比较闲的时候,见缝插针的刷一点“脏页”。

4. MySql正常关闭

正常关闭时,会把内存中的脏页都刷到磁盘里。

上述几种场景对性能的影响

1. redolog 满了

这种情况要尽量避免,因为这种场景下,整个系统都不能再接受更新了。

2. 内存不足了

InnoDB使用buffer pool 管理内存,缓冲池中的内存页有三种状态:

  1. 还没用的(很少)
  2. 用过了的干净页
  3. 用过了的脏页

如果LRU淘汰了前两种,都没啥影响,但淘汰了脏页,就要先将脏页刷磁盘变成干净页,然后再复用这个内存空间。
如果有如下两种情况,会明显的影响性能:

  1. 一个查询要淘汰的脏页太多,导致查询的响应时间明显变长
  2. 日志写满了,更新都阻塞了,写性能降为0,对于敏感业务,这种是不可接受的

如何避免上述情况 – InnoDB刷脏页的控制策略

首先要告诉InnoDB,其所在的主机正确的IO能力

这样InnoDB才知道全力flush,可以刷多快。

这里要用到 innodb_io_capacity参数。磁盘的IOPS可以通过fio这个工具来测试。

控制策略

要关注两个因素:脏页比例redolog写盘速度
InnoDB会根据这两个因素单独算出两个数字。并用其中的最大值来控制刷脏页的速度。

innodb_max_dirty_pages_pct:脏页比例上限,默认75%
MySql-丁奇-学习笔记-为啥我的MySql会抖一下?(flush机制)_第2张图片

小结

要合理设置innodb_io_capacity,平时要多关注脏页比例,不要让它轻易接近75%。

求脏页比例代码参考如下:

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;

连坐策略

一旦一个查询请求需要在执行过程中先 flush 掉一个脏页时,这个查询就可能要比平时慢了。而 MySQL 中的一个机制,可能让你的查询会更慢:在准备刷一个脏页的时候,如果这个数据页旁边的数据页刚好是脏页,就会把这个“邻居”也带着一起刷掉;而且这个把“邻居”拖下水的逻辑还可以继续蔓延,也就是对于每个邻居数据页,如果跟它相邻的数据页也还是脏页的话,也会被放到一起刷。

在 InnoDB 中,innodb_flush_neighbors 参数就是用来控制这个行为的,值为 1 的时候会有上述的“连坐”机制,值为 0 时表示不找邻居,自己刷自己的。

找“邻居”这个优化在机械硬盘时代是很有意义的,可以减少很多随机 IO。机械硬盘的随机 IOPS 一般只有几百,相同的逻辑操作减少随机 IO 就意味着系统性能的大幅度提升。
而如果使用的是 SSD 这类 IOPS 比较高的设备的话,我就建议你把 innodb_flush_neighbors 的值设置成 0。因为这时候 IOPS 往往不是瓶颈,而“只刷自己”,就能更快地执行完必要的刷脏页操作,减少 SQL 语句响应时间。

在 MySQL 8.0 中,innodb_flush_neighbors 参数的默认值已经是 0 了。

思考

一个内存配置为 128GB、innodb_io_capacity 设置为 20000 的大规格实例,正常会建议你将 redo log 设置成 4 个 1GB 的文件。
但如果你在配置的时候不慎将 redo log 设置成了 1 个 100M 的文件,会发生什么情况呢?又为什么会出现这样的情况呢?

你可能感兴趣的:(MySql,mysql)