Undo Log
Undo Log 记录数据修改前的旧版本信息,用于事务回滚,并为 InnoDB 中的 MVCC 提供旧版本可见性支撑。
#type / concept
#status / growing
#tech / dev / backend
#resource / database
#resource / mysql
[!info] related notes
Undo Log
一句话定义
Undo Log 是 InnoDB 为保存修改前旧版本而维护的撤销日志,主要服务于事务回滚和 MVCC 旧版本可见性。
它要解决什么问题
数据库修改一行数据时,不仅要考虑“新值怎么生效”,还要考虑两件事:
- 如果事务失败,怎么撤回到修改前
- 如果别的事务暂时还不能看到新值,旧版本从哪里来
Undo Log 就是这两件事的共同支撑。
核心机制 / 工作原理
1. Undo Log 记录的是“修改前长什么样”
当事务修改一行时,数据库需要保存足够的旧版本信息,以便后续:
- 回滚
- 生成或还原可见旧版本
所以 Undo Log 的关注点是:
- 撤销修改需要什么
- 旧值链路如何保存
而不是“提交后怎么重做”,那是 Redo Log 更关心的事。
2. 回滚依赖 Undo Log
如果事务在中途失败,或者应用显式执行 ROLLBACK:
- 数据库要能把已经做过的改动撤回
- 撤回动作需要知道旧值是什么
Undo Log 就是数据库回到旧状态的重要依据。
3. MVCC 也常依赖 Undo Log 提供旧版本
在 InnoDB 语境里,Undo Log 不只是“回滚时用一次”。
它还常被用来支撑:
- 某个读事务要读取旧快照时
- 当前最新版本对它不可见时
- 数据库沿着版本链回退到它应该看到的旧版本
所以 Undo Log 和 MVCC 的关系非常紧。
最小例子 / 最小场景
事务 A 把用户余额从 100 改成 80,但还没提交。此时事务 B 仍可能需要看到旧值 100。
InnoDB 可以借助 Undo Log 提供这份旧版本信息;如果事务 A 后来失败,也可以借助它把余额撤回到 100。
从原理上最该抓住什么
1. Undo Log 同时服务“回滚”和“旧版本可见性”
这也是它最容易被低估的地方。它不是单纯的“失败时擦屁股工具”,而是并发可见性链路的一部分。
2. Undo Log 和 MVCC 不是同一个概念
更准确的关系是:
- MVCC 是并发控制机制
- Undo Log 是 InnoDB 用来支撑其中一部分旧版本可见性的实现基础
3. 长事务会拖住 Undo 相关版本清理
因为旧事务还可能需要看到老版本,所以一些旧版本不能太早回收。
这也是为什么长事务常常会放大:
- 版本堆积
- 回收压力
- 存储和性能成本
边界与易混淆点
- Undo Log 主要不是为了“已提交后的崩溃重做”,那是 Redo Log 更关心的事。
- Undo Log 和 MVCC 关系很紧,但 MVCC 是并发控制机制,Undo Log 是支撑机制之一。
- 不是所有数据库都用和 InnoDB 一样的方式实现旧版本可见性。
- “有 Undo Log 就一定能无限保留历史版本”也是误解,旧版本能保留多久受事务生命周期和回收机制约束。