先说结论

Redo Log 负责崩溃恢复,Undo Log 负责回滚和历史版本,Binlog 负责复制与增量恢复。三者分工不同,事务提交时又需要配合,才能兼顾数据库内部恢复和 Server 层日志一致。

三类日志对比

日志 所属 主要内容 核心用途
Redo Log InnoDB 存储引擎 页修改相关的物理/逻辑信息 崩溃恢复、保证已提交修改持久性
Undo Log InnoDB 存储引擎 修改前版本或反向操作信息 事务回滚、MVCC 历史版本
Binlog MySQL Server 层 数据变更事件 主从复制、CDC、时间点恢复、审计

三者不是互相替代关系。一次事务更新可能同时产生 Undo、Redo 和 Binlog,各自服务不同目标。

Redo Log 为什么需要

InnoDB 修改数据时通常先更新 Buffer Pool 中的数据页,这些脏页不会每次提交都立即随机写回数据文件。事务提交前先把对应 Redo 按策略持久化,后续即使系统崩溃,也可以在启动时重放已提交修改。

这就是 Write-Ahead Logging:描述修改的日志必须先于脏数据页持久化。日志写入通常比到处随机刷新数据页更连续、更高效。

Redo Log Buffer 先收集日志记录,再根据事务提交和配置刷入操作系统缓存或磁盘。innodb_flush_log_at_trx_commit 会影响持久性与性能取舍,不能只为吞吐随意降低安全级别。

Undo Log 的两种职责

事务回滚时,InnoDB 根据 Undo 中的信息把修改反向恢复。对于更新,Undo 还将旧版本串成版本链,一致性读依据 Read View 找到可见版本。

事务提交后 Undo 不一定立刻删除。只要仍有旧 Read View 可能访问这些版本,Purge 就不能清理。长事务会让历史版本持续积累,增加空间和查询成本。

Undo 本身的变更也需要 Redo 保护,保证崩溃恢复过程中回滚信息处于一致状态。

Binlog 的格式

  • Statement:记录原始 SQL,体积可能较小,但某些非确定函数和执行环境会带来不一致风险。
  • Row:记录行级变更,更可靠地复现结果,是常见生产选择,但日志量可能更大。
  • Mixed:由服务器在 Statement 与 Row 间选择。

Row 格式并不意味着记录完整数据的方式永远相同,还受行镜像配置影响。生产修改前要同时考虑恢复能力、CDC 兼容性和日志体积。

两阶段提交解决什么问题

Redo 属于 InnoDB,Binlog 属于 Server 层。若分别提交,进程在两者之间崩溃可能出现:数据页能通过 Redo 恢复,但 Binlog 没有对应事件;或者 Binlog 已写而引擎事务未成功。这会导致主库与复制、恢复结果不一致。

简化过程如下:

1. InnoDB 写 Redo,并标记 prepare
2. Server 写 Binlog
3. InnoDB 将 Redo 标记 commit

恢复时结合 Redo 状态与 Binlog 中是否存在对应事务决定提交或回滚。实际实现还涉及组提交、刷盘和内部状态,先抓住跨层日志原子一致这个目标即可。

组提交

若每个事务都单独执行一次磁盘同步,吞吐会受到严重限制。组提交将多个并发事务的日志刷盘合并,分摊同步成本。它不改变事务原子性,而是优化日志持久化路径。

日志与备份恢复

全量备份提供某一时间点的数据基线,Binlog 可以把数据重放到目标时间点。可靠恢复必须同时验证备份文件可用、Binlog 连续、时间边界准确,并定期进行恢复演练。

误删恢复不应直接在原库盲目重放。通常在隔离环境恢复全量备份,重放到误操作前,再校验并回迁目标数据。

常见故障场景

  • Redo 空间压力高:脏页刷新跟不上、写入突增或存储延迟高。
  • Undo 历史过长:存在长事务或 Purge 速度不足。
  • Binlog 磁盘占满:保留策略、备份消费或异常写入需要检查。
  • 复制延迟:大事务会在 Binlog 中形成大事件,副本应用耗时增加。

常见问题

追问 1:只靠 Binlog 能做崩溃恢复吗?

Binlog 是 Server 层逻辑变更日志,不负责恢复 InnoDB Buffer Pool 中尚未刷回数据文件的页状态。引擎崩溃恢复主要依赖 Redo。

追问 2:事务提交后 Undo 为什么不能立刻删除?

其他长事务的 Read View 可能仍需要旧版本。只有没有活跃视图再访问时,Purge 才能安全清理。

追问 3:Redo Log 和 Binlog 都记录修改,为什么需要两个?

Redo 面向 InnoDB 页级恢复且与引擎实现紧密相关;Binlog 面向 Server 层的数据变更传播与恢复,适用于复制和 CDC,职责不同。

追问 4:两阶段提交会不会性能很差?

它增加协调步骤,但 MySQL 通过组提交等机制合并刷盘成本。可靠性与吞吐需要综合配置,不应为了少一次同步破坏跨日志一致性。

追问 5:设置 sync_binlog=0 有什么风险?

依赖操作系统自行刷新,操作系统或机器崩溃时可能丢失尚未持久化的 Binlog。具体配置要结合可接受的数据损失目标和存储能力。