先说结论
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。具体配置要结合可接受的数据损失目标和存储能力。