Redo Log 能保证 crash-safe,根本原因在于它强制实现 WAL 机制:事务提交前必须先将物理页变更落盘,崩溃后通过重放已持久化日志即可恢复数据;它记录的是数据页指定偏移量的字节级修改,而非 SQL 语句或行级逻辑。

Redo Log 能保证 crash-safe,根本原因在于它强制实现了 WAL(Write-Ahead Logging)机制:事务提交前,必须先把物理页变更落盘;崩溃后,MySQL 只需重放这些已持久化的日志,就能把磁盘数据追上内存状态。
Redo Log 记录的是什么,不是什么
它不记录 SQL 语句、不记录行级逻辑、也不关心业务含义。只记录「某个数据页的某个偏移量处,几个字节从旧值变成了新值」——例如:page 123, offset 48, 4 bytes: 0x1234 → 0x5678。这种物理页变更粒度,让重放(replay)过程极快且确定。
常见错误现象:误以为 SHOW ENGINE INNODB STATUS 里看到的 LOG 段能直接读出 SQL;或试图用 mysqlbinlog 解析 ib_logfile0 —— 这两类操作都失败,因为 redo log 不是文本日志,也非逻辑日志。
- 它由
ib_logfile0和ib_logfile1组成,默认共 96MB(innodb_log_file_size × 2),环形覆盖 - 日志写满后自动覆盖最老的,不增长,也不归档
- 无法手动“清空”或“截断”,只能通过调整大小并重启生效
Crash 后恢复靠的是 checkpoint + 前滚(roll forward)
MySQL 启动时,并不会重放全部 redo log,而是先定位到最近一次 checkpoint 的位置(即当时已刷盘的脏页边界),然后从那里开始顺序解析、应用后续所有 prepare/commit 状态的日志项。
关键点在于:只有状态为 COMMIT 的 redo log 才会被重放;PREPARE 但未完成两阶段提交的,会结合 binlog 判断是否补 commit 或回滚(这就是两阶段提交的意义)。
- checkpoint 本身不保证数据页已刷盘,只标记“这个位置之前的数据页,理论上应该已刷盘”
- 如果后台线程刷脏页慢,checkpoint 落后较多,启动恢复时间就长
- 恢复过程不依赖 undo log —— undo log 是用于回滚未提交事务的,和 crash-safe 无直接关系
innodb_flush_log_at_trx_commit 是 crash-safe 的开关
这个参数直接决定 redo log 是否真正在事务提交时落盘。设为 0 或 2 时,COMMIT 返回成功,但日志可能还卡在 OS cache 里,服务器断电就会丢数据 —— 此时已失去 crash-safe 能力。
线上生产环境必须设为 1,否则所谓“已提交事务不丢失”就是空谈。
-
1:每次COMMIT都调用fsync()写入磁盘,强持久性 -
0:每秒fsync一次,崩溃最多丢 1 秒内已提交事务 -
2:每次COMMIT写入 OS page cache,再由 OS 异步刷盘;OS 崩溃会丢数据
性能瓶颈若出现在这里,优先排查锁竞争、索引缺失或大事务,而不是调低该值 —— 它不是性能调优项,而是数据安全底线。
真正容易被忽略的是:crash-safe 仅针对「已提交事务」。如果事务还没 commit 就崩溃,那部分修改靠 undo log 回滚,和 redo log 无关;而两阶段提交中 binlog 和 redo log 的状态协同,才是主从一致的前提,不是 crash-safe 本身的要求。











