09.三大日志(Redo、Undo、Binlog)与恢复机制
文章目录
问题: 请区分Redo Log、Undo Log和Binlog各自的用途;说明WAL技术和MySQL内部两阶段提交(2PC)是如何保证事务崩溃恢复时数据一致性的?
👇 点击展开/折叠 面试背诵模板(建议先背这个)
一、三大日志的职责边界
| 日志类型 | 所属层级 | 日志格式 | 写入方式 | 核心用途 |
|---|---|---|---|---|
| Redo Log | InnoDB引擎 | 物理日志(页级修改,如“在页X偏移Y处写入值Z”) | 循环写入(固定大小,写满后覆盖) | 崩溃恢复(重放已提交事务),保证持久性 |
| Undo Log | InnoDB引擎 | 逻辑日志(逆操作,如“删除对应插入记录”) | 存储于表空间的Undo段(可被Purge线程清理) | 事务回滚 + MVCC(提供一致性读快照),保证原子性 |
| Binlog | MySQL Server层 | 逻辑日志(Statement/Row/Mixed格式) | 追加写入(非循环,可归档) | 主从复制 + 基于时间点的增量恢复(PITR) |
二、WAL(预写日志)技术的核心价值
WAL(Write-Ahead Logging)要求:在修改数据页之前,必须先将修改操作写入Redo Log,并保证Redo Log在事务提交时落盘(fsync),数据页则延迟到合适时机(检查点)异步刷盘。
- 性能优化:数据页写入是随机I/O,Redo Log写入是顺序I/O。WAL将随机I/O转换为顺序I/O,极大提升写入吞吐量。
- 持久性保证:即使数据页未刷盘时宕机,重启后通过重放Redo Log即可恢复到宕机前状态,保证已提交事务的持久性。
三、内部两阶段提交(2PC)的一致性保证机制
为何需要2PC:Redo Log(引擎层)和Binlog(Server层)在逻辑上是独立的。若Redo Log已提交但Binlog未写,主从复制会丢失数据;反之,若Binlog已写但Redo Log未提交,从库数据会多于主库(主从数据不一致)。MySQL通过内部XA事务(两阶段提交)协调两者状态。
两阶段提交具体流程:
- Prepare阶段:将事务的Redo Log落盘,并在日志中标记为 Prepare(准备) 状态。
- Commit阶段(分为两步):
- 将事务的Binlog落盘(fsync)。
- 将Redo Log状态从Prepare改为 Commit(提交)(无需立即落盘,仅更新内存标记)。
崩溃恢复规则(关键):
- 若重启时发现事务在Redo Log中处于Prepare状态:
- 检查对应的Binlog是否完整(已落盘且包含该事务)。
- Binlog已写 → 将该事务提交(重放Redo Log)。
- Binlog未写 → 将该事务回滚(利用Undo Log撤销修改)。
- 若Redo Log状态为Commit,则直接提交。
结论:这种机制确保Binlog和Redo Log的最终状态完全一致——要么都包含该事务(提交),要么都不包含(回滚),从而保证主从复制和数据恢复的绝对一致性,实现Crash-Safe能力。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 LGQ的博客!