UndoLog 是 InnoDB 实现事务原子性与一致性的逻辑日志,记录反向操作(如 INSERT 对应 DELETE),用于回滚和 MVCC;它非备份日志,不负责崩溃恢复,存储于 undo 表空间,由 purge 线程异步清理。

UndoLog 是 SQL 数据库(尤其是 InnoDB)实现事务原子性和一致性的重要机制,核心作用是在事务执行失败或主动回滚时,将已修改但未提交的数据恢复到事务开始前的状态。
UndoLog 是什么?不是“日志备份”
UndoLog 不是数据库的全量备份,也不是用于崩溃恢复的主日志(那是 RedoLog 的职责)。它是一组按事务组织的、记录“反向操作”的逻辑日志。例如:
- INSERT 操作对应的 UndoLog 记录一条 DELETE(按主键定位原记录);
- UPDATE 某字段从 A→B,UndoLog 记录该字段从 B→A 的还原信息;
- DELETE 操作对应一条 INSERT(含完整行数据),用于重建被删记录。
这些日志保存在共享表空间或独立的 undo tablespace 中,以段(undo segment)为单位分配,由事务 ID 关联管理。
事务回滚时 UndoLog 如何工作?
当执行 ROLLBACK 或事务因异常中断时,InnoDB 并不逐条重放 UndoLog,而是按事务的 undo log 链逆序扫描,对每个修改生成对应的逆操作,并直接应用到内存中的数据页(Buffer Pool):
- 回滚只影响本事务修改过的记录,不影响其他并发事务的可见性;
- 回滚过程持有行锁(防止其他事务同时修改同一行),但不阻塞读(MVCC 保证);
- 回滚完成后,该事务的 undo log 会被标记为可清除,后续由 purge 线程异步清理。
UndoLog 和 MVCC 的关系密不可分
除了回滚,UndoLog 还支撑了多版本并发控制(MVCC):每个 SELECT 查询根据事务的一致性视图(read view),从最新版本向前遍历 undo log 链,找到本事务可见的“快照版本”。这意味着:
- 一个 long-running 查询可能需要访问很老的 undo 版本,若 undo log 被过早 purge,会报错 “Snapshot too old”;
- innodb_max_undo_log_size、innodb_undo_retention 等参数直接影响历史版本保留能力;
- 大事务(如全表 UPDATE)会生成大量 undo 日志,既拖慢回滚速度,也加剧 purge 压力。
运维和调优中需关注的关键点
实际使用中,UndoLog 相关问题常表现为回滚慢、空间暴涨或 purge 延迟:
- 避免在事务中执行大批量 DML;拆分为小批量 + 显式提交;
- 监控 red">information_schema.INNODB_TRX 表,及时发现长事务阻塞 purge;
- 启用独立 undo 表空间(innodb_undo_directory)便于管理和收缩;
- MySQL 8.0+ 支持在线 truncate undo 表空间,可在低峰期回收碎片空间。










