redo log 常被概括成“崩溃恢复日志”,这个说法没错,但容易把重点带偏。它真正支撑的是 WAL:事务提交时先拿到可恢复性,数据页可以留在内存里,之后再由刷盘和 checkpoint 慢慢把债务还掉。

理解 redo,要同时看两个问题:为什么提交不要求数据页立刻落盘,以及为什么写入压力积累后又会反过来造成抖动。redo 的价值和代价,都在这条链路里。

先把机制边界说清楚

redo log 是 InnoDB 的物理重做日志,记录的是数据页层面的修改意图。它支撑 WAL 机制:事务修改数据页时,先写 redo,数据页可以稍后再刷盘。只要 redo 持久化成功,崩溃后就能把已提交修改重放回来。

整体路径

redo log:MySQL 不丢数据的关键

上面这张图先看入口和边界:宏观上,更新语句会先在 Buffer Pool 中修改数据页,同时生成 redo log record 写入 redo log buffer。提交时根据参数把 redo 刷到磁盘;后台线程再逐步把脏页刷回数据文件,并推进 checkpoint,释放 redo 可覆盖空间。

WAL:先写日志后写数据页

第二张图再看结构关系。

底层流程

redo log 的循环写结构

底层拆解先看数据结构。「redo log」至少涉及下面几类结构:

  • redo log record:描述某个页上发生的物理修改。
  • redo log buffer:事务执行过程中暂存 redo 的内存区域。
  • redo log file:磁盘上的循环日志空间。
  • LSN:全局递增的日志序号,用来关联页版本和 checkpoint。
  • checkpoint:表示哪些 redo 已经被数据页刷盘覆盖。

再看完整执行流程:

  1. 事务修改 Buffer Pool 中的数据页。
  2. InnoDB 生成 redo log record 并写入 log buffer。
  3. 提交时按 innodb_flush_log_at_trx_commit 策略刷盘。
  4. 后台线程把脏页刷回数据文件。
  5. checkpoint 推进后,旧 redo 空间可以被复用。
  6. 崩溃恢复时从 checkpoint 后重放 redo。

取舍与边界

redo log 的崩溃恢复流程

版本差异上,MySQL 8.0.30 之后更推荐通过 innodb_redo_log_capacity 管理 redo 容量,早期版本常用 innodb_log_file_size 和文件个数。参数形态会变,但 WAL、LSN、checkpoint 和崩溃恢复的关系没有变。

redo log 的短板是它把随机刷数据页变成顺序写日志,但没有让刷盘成本消失。redo 空间太小、checkpoint 推进慢、磁盘 fsync 抖动或大事务集中写入,都会让前台提交被迫等待。

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

写入抖动可以从 redo 和 checkpoint 看:更新本身可能很快,但 redo 空间、脏页比例和刷盘能力跟不上时,提交链路会被迫等待后台还账。

可以落到这些动作:

  • 监控 redo 使用率、checkpoint age、fsync 延迟和脏页比例。
  • 写密集场景不要只看 SQL 单次耗时,要看后台刷盘能否持续还账。
  • 控制大事务行数,避免一次制造大量 redo 和脏页。
  • 参数调优必须结合磁盘能力,不能只复制网上模板。

收束:redo 是性能和恢复的交易

redo log 让 InnoDB 可以先写日志、后刷数据页。它把提交路径变轻,也把刷盘债务留给 checkpoint 和后台线程;写入稳定性要同时看这两面。


关于十三Tech

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

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

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

十三Tech公众号二维码