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 就一定能无限保留历史版本”也是误解,旧版本能保留多久受事务生命周期和回收机制约束。
创建于 2026/5/5 更新于 2026/5/27