Redo日志记录物理页变更以保证持久性,崩溃后重放已提交事务;Undo日志记录逻辑前镜像以支持回滚和MVCC一致性读,两者协同实现ACID。

Redo 日志记录“做了什么操作”,用于崩溃恢复时重放已提交事务;Undo 日志记录“原来是什么样子”,用于回滚未提交事务、提供一致性读(MVCC)。
Redo 日志:保证持久性(Durability)
Redo 日志是物理日志,记录数据页的变更细节(比如“在某个数据页的第120字节处,把值从 0x1A 改成 0x2B”)。它写入快、顺序写、先于数据页落盘。
- 事务提交时,只要 Redo 日志刷盘成功,就算崩溃也能恢复——InnoDB 重启后会扫描 Redo 日志,把已提交但还没写入数据文件的修改重新应用一遍
- Redo 日志是循环复用的,由多个固定大小的文件组成(如 ib_logfile0、ib_logfile1),通过 LSN(Log Sequence Number)标记位置和进度
- 不记录 SQL 语句或逻辑操作,只记录底层页级变更,所以无法直接用于闪回或审计
Undo 日志:支持回滚与多版本并发控制(MVCC)
Undo 日志是逻辑日志,记录事务修改前的数据镜像(比如“某行原来的 name 是 'Alice',被更新为 'Bob',那就存下 'Alice'”)。它保存在共享表空间或独立 Undo 表空间中。
- 事务执行过程中,每条 INSERT/UPDATE/DELETE 都会生成对应的 Undo 记录;事务回滚时,就按这些记录反向还原数据
- SELECT 查询需要读取“过去某一时刻”的数据(快照读)时,InnoDB 会结合 Undo 链找到对应版本,实现非阻塞读
- Undo 日志不能立刻删除——必须等到所有可能用到它的活跃事务(包括长事务、正在做快照读的事务)都结束后,才能被 purge 线程清理
两者协同工作的典型场景
假设执行一条 UPDATE 语句:
- InnoDB 先在内存中修改数据页,并把旧值写进 Undo 日志(生成一个 Undo Log Record)
- 再把这次修改的操作(页号、偏移、新值等)写入 Redo 日志缓冲区,随后刷盘
- 事务提交后,Redo 日志确保修改不会丢失;若此时崩溃,恢复时靠 Redo 重做;若事务中途失败,则靠 Undo 回滚
- 其他事务并发 SELECT 时,通过 Read View 和 Undo 链判断该行哪个版本对自己可见
常见误区提醒
red">Redo 不是 binlog:Redo 是 InnoDB 引擎层日志,仅用于崩溃恢复;binlog 是 Server 层日志,用于主从复制和归档,格式可为 statement、row 或 mixed。
Undo 不等于回滚段(Rollback Segment)的全部:老版本 MySQL 中 Undo 存在系统表空间的回滚段里;MySQL 5.6+ 支持独立 Undo 表空间,更易管理与截断。
Redo 写满会阻塞事务:如果 Redo 日志空间不足(比如 checkpoint 落后太多),新事务可能被卡住等待刷脏页,表现为“Waiting for redo log space”。










