事务提交不要求数据页立刻落盘,这是 redo log 带来的能力;但被修改过、还没刷回磁盘的页不会凭空消失,它们会以脏页的形式留在 Buffer Pool 里。

脏页机制把写入主路径变快了,也把刷盘成本延后了。问题在于,延后的债务迟早要还:checkpoint 推进、后台刷盘、磁盘能力和写入突增都会影响系统抖动。

先把机制边界说清楚

脏页指 Buffer Pool 中已经被修改、但还没刷回磁盘的数据页。事务提交时依赖 redo log 保证崩溃恢复,不要求数据页立刻落盘,所以更新可以先改内存,再由后台线程慢慢刷脏。

整体路径

脏页与刷盘:为什么更新偶尔会抖一下

上面这张图先看粗线条:宏观上,写入路径分成两条线:前台事务写 redo 并修改 Buffer Pool,后台线程推进 checkpoint 并把脏页刷回磁盘。只要后台刷盘能跟上,前台就稳定;一旦 redo 空间逼近、脏页比例过高或需要淘汰脏页,前台请求就会被拖住。

底层流程

脏页与刷盘:为什么更新偶尔会抖一下:执行路径

底层拆解先看数据结构。「脏页与刷盘」至少涉及下面几类结构:

  • 脏页:内存内容比磁盘新的页。
  • Flush List:按最早修改 LSN 管理脏页。
  • Checkpoint:标记 redo 已覆盖到哪个持久化点。
  • redo log:崩溃恢复时重放脏页修改。

再看完整执行流程:

  1. 事务更新记录,修改 Buffer Pool 页。
  2. 写 redo log,保证崩溃可恢复。
  3. 页进入脏页链表。
  4. 后台线程按策略刷脏推进 checkpoint。
  5. 刷盘压力过大时前台写入被动等待。

取舍与边界

版本差异上,MySQL 5.7 以后 InnoDB 刷盘策略已经较成熟,8.0 在 redo log 配置、并发刷盘和监控可观测性上继续增强。不同版本参数名和默认值会变化,但脏页与 checkpoint 的关系不变。

脏页机制的短板是成本延迟。提交时看似很快,但刷盘债务会积累;大事务、突发写入、低 io_capacity 或慢盘都会让债务在某一刻集中爆发。

典型问题:用机制化例子排查

批量更新不只制造 redo,也会制造大量脏页。提交完成不代表成本结束,如果后台刷盘跟不上,后续请求会替前面的写入压力还账。

可以落到这些动作:

  • 控制单事务修改规模,避免一次制造过多脏页。
  • 根据磁盘能力设置 innodb_io_capacity 和相关刷盘参数。
  • 监控脏页比例、checkpoint age、redo 使用率和 fsync 延迟。
  • 写入高峰前避免大 DDL、大批量更新和报表扫描叠加。

收束:写入稳定性看后台还账

脏页与刷盘告诉我们:写入性能不是只看提交那一刻,而要看后台能否平滑还账。稳定性来自持续刷,而不是最后硬刷。


关于十三Tech

我是十三,All in AI Agent 方向的架构师,专注 AI 工程实践。

我相信 AI 是程序员的最佳搭档,也希望帮助每一位开发者更好地驾驭 AI。

如果你想继续跟完这套「图解 MySQL」,欢迎关注公众号 「十三Tech」。后续会继续按机制、图解和实战排查这条线更新。

十三Tech公众号二维码