Redo Log与Undo Log是解决不同问题的独立机制:Redo保障已提交事务持久性,为物理日志,记录数据页修改;Undo保障原子性与MVCC,为逻辑日志,记录反向操作。

Redo Log 和 Undo Log 不是互为反向操作的“一对日志”,而是解决不同问题的两种独立机制:Redo 保证已提交事务不丢,Undo 保证未提交事务可撤、同时支撑 MVCC。
Redo Log 是物理日志,记录“怎么把数据页改到新状态”
它由 InnoDB 引擎生成,内容是磁盘数据页的物理变更(比如“第123页偏移456处写入8字节新值”),不是 SQL 语句。写入走 WAL(Write-Ahead Logging)路径:事务修改内存中的页 → 同步写入 redo log buffer → 按 innodb_flush_log_at_trx_commit 策略刷盘到 ib_logfile0 等文件。
- 崩溃恢复时,MySQL 重放(replay)这些物理操作,把宕机前已提交但尚未刷盘的脏页“重做”出来
- 日志文件固定大小、循环复用,
ib_logfile0写满就切到ib_logfile1,不手动清理 - 即使事务回滚了,它的 redo 日志也不会被删除——因为已提交事务的持久性不能因其他事务失败而动摇
Undo Log 是逻辑日志,记录“怎么回到修改前的样子”
它也由 InnoDB 管理,但内容是逻辑反向操作(比如 “INSERT 对应 DELETE”,“UPDATE 记录旧值”)。每行数据的多个版本通过指针连成链表,构成 MVCC 的基础。
- 事务回滚时,顺着 undo 链表把新值替换成旧值;不是靠“撤销 redo”,而是直接覆盖回退
- 未提交事务的 undo 日志在事务结束后可能立即失效,但已提交事务的 undo 日志不会马上删——要等所有可能依赖该版本的快照读事务都结束,才由
purge线程异步清理 - 它不参与崩溃恢复,只服务于事务原子性和一致性(ACID 中的 A 和 I)
两者根本不在同一层协作,别混淆“重做”和“回滚”的触发条件
常见误解是“undo 用来 undo redo”,其实完全不是:
-
ROLLBACK时,InnoDB 用 undo 日志还原数据,跟 redo 日志无关 - 实例崩溃重启后,InnoDB 先用 redo 日志恢复所有已提交事务的最新状态,再根据 undo 日志判断哪些事务没提交——对这些事务执行回滚(此时才用到 undo)
- redo 日志刷盘时机受
innodb_flush_log_at_trx_commit控制,而 undo 日志写入是事务开始即发生的,且必须先于 redo 落盘(WAL 要求)
真正容易被忽略的是:undo 日志的生命周期由并发读事务决定,不是由自身事务状态决定;而 redo 日志只要被 checkpoint 覆盖过,就彻底失去作用——这个边界一旦搞混,排查长事务导致的 undo tablespace 膨胀或 log file full 就会跑偏。


















