MySQL刷页的时机

InnoDB通过redolog确保数据持久化,避免随机IO的低效,当redolog满或内存不足时会触发刷页。脏页在数据库空闲、内存不足或关闭时会被刷入磁盘。控制刷页的参数包括脏页比例和redolog写入序号,通过函数计算决定刷页速度。针对刷页导致的性能问题,MySQL提供了脏页比例上限和磁盘最大IO能力参数,并有针对机械硬盘优化的‘连坐’机制,固态硬盘环境下可通过配置关闭此机制。
摘要由CSDN通过智能技术生成

在上一篇文章《MySQL的日志系统》中,介绍了redo log的作用。由于内存中的数据不稳定,为了数据安全,必须保证每次修改都能持久化到硬盘中,但是对于硬盘中的记录进行修改需要随机IO,效率非常低。
为了解决这个问题,InnoDB引入了redo log,记录每次修改的页及具体修改的数据,对redo log的写是顺序写,比起随机IO要快上许多。
InnoDB会在合适的时机再将这些修改后的数据真正持久化到硬盘中的数据库表中,这个操作称之为刷页,当内存数据页中的数据与硬盘中的数据不一致时,这个内存数据页就称之为脏页,刷页可以将脏页变成干净页。而合适的时机就是本文要探讨的问题了

1. 合适的时机
  • redo log写不下了。redo log作为持久化的保障,每次更新操作都必须记录,如果redo log写不下了,那么就必须进行刷页,将数据同步到磁盘中,然后移动redo log 的checkpoint指针,空出新的位置,如果此时内存不紧张,那么刷完的页不需要淘汰出内存
  • 内存放不下数据页了。查询操作会将磁盘中的数据页读入内存,然后再进行返回,如果内存放不下数据页了,那么就必须淘汰最久未使用的数据页,如果该数据页是脏页,那么必须刷进磁盘然后淘汰。
  • 数据库空闲时。如果数据库认为当前是一个空闲状态时,那么就会对脏页进行刷页,此时内存如果不紧张,那么刷完后不进行淘汰
  • 数据库正常关闭时。数据库关闭的时候,也会进行刷页,将之前做的修改持久化到硬盘

以上四点就是刷页的时机,其中第二点是最常见的。由于内存的访问速度比之磁盘要快上很多倍,因此InnoDB对内存的使用十分频繁,从1、3点也可以看出,在内存不紧张时已刷的页是不进行淘汰的,而是等到内存不够用时再淘汰。
前文提到redo log是用来保证持久化的,那么内存不够时是否能够直接淘汰数据页,收到请求时再从硬盘读取并用redo log同步呢?这其实是为了性能考虑,直接从内存刷新总要比读取硬盘再刷新快。

因此redo log实际上一种保底手段,正常情况刷页是不会用到redo log的,而是直接将内存脏页刷新到硬盘的表数据当中。只有当数据库崩溃时,才会使用到redol og,使用步骤是:

  • 先将因为崩溃而丢失更新的数据页读取到内存中
  • 再使用redo log将内存中的数据页恢复更新,变成脏页,然后按照刷页规则最终落盘

也就是说,哪怕是使用到redo log,也不是直接将其更新到硬盘表中,redo log并没有数据页的完整数据,不具备直接更新磁盘数据页的功能

淘汰脏页是最久未使用的页,在redo log中是随机存储的,当需要用redo log重放时会跳过这一部分日志。

2. 刷页带来的问题

刷页需要进行随机IO,自然不是一个轻量级操作,因此有时一些更新语句比较慢,那么可能就是因为刷页的原因,如果一次刷页时间过长,那么会使得业务进度十分缓慢甚至停滞,这是不可接受的,因此MySQL采用了脏页控制手段来避免。
从刷页的时机入手,如果数据库空闲或者已经进行了关闭,那么性能问题就不是我们所关注的,因此MySQL的控制手段主要是根据1、2点进行控制,也即从redo log写的情况和内存中的脏页比例入手

  • 控制内存脏页比例的参数是当前参数比例,将该参数简单记为N,根据这个参数利用函数算出一个0-100之间的数字,记为F1(N)
  • 控制redo log的参数是写入序号,InnoDB写日志时都会标上序号,当前写入序号和checkpoint写入序号的差值就是控制参数了。将该参数简单记为M,用该参数调用函数算出一个0-100之间的数字,记为F2(M)
  • InnoDB有参数innodb_max_dirty_pages_pct,用来控制脏页比例上限,默认为75%,将其记为R%,将F1(N)和F2(M)取较大值乘以R%就可以用来控制刷页速度了

此外InnoDB还提供了一个参数innodb_io_capacity,用来指定磁盘的最大IO能力,根据该参数调整刷页速度。而刷页还有一个“连坐”机制,如果一个脏页下一页也是脏页,那么会顺着下一个脏页不停刷,直到旁边没有脏页,这样一来会使得查询语句执行很慢。这样设置主要是因为机械硬盘的IOPS很低,连坐可以减少随机IO,从而大幅度提高性能。而如果是固态硬盘则没有必要这样做,可只刷当前页,提高查询效率,MySQL中提供了一个参数innodb_flush_neighbors来控制,设置为0即可关闭连坐。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值