undolog

14 阅读2分钟

image.png Undo Log 的正确定义Undo Log(回滚日志) 记录的是 数据被修改之前的旧版本(before image)。

  • 当一个事务对一行数据进行 INSERT / UPDATE / DELETE 时,InnoDB 会先把修改前的旧数据 保存到 Undo Log 中。
  • 同时,这一行当前记录的 trx_id 会更新为当前事务的 ID。
  • 通过 roll_ptr(回滚指针),把新版本和旧版本串成一条版本链。

举例说明(最直观)假设表中原来有一行数据:

  • id=1, name="张三", trx_id=50(很早以前的事务修改的)

现在事务 ID=200 执行 UPDATE 把 name 改成 "李四":

  1. InnoDB 先把旧数据(name="张三", trx_id=50)写入 Undo Log。
  2. 然后把当前行改成 name="李四", trx_id=200。
  3. 当前行通过 roll_ptr 指针指向刚才写入的 Undo Log。

结果版本链(从新到旧):

  • 当前记录: name="李四", trx_id=200 ← 新版本
  • Undo Log 中: name="张三", trx_id=50 ← 旧版本

Undo Log 里保存的是“旧的、被覆盖之前的数据”,而不是“提交后的数据”。Undo Log 的两大主要作用

  1. 事务回滚(Rollback)
    如果事务执行失败或用户执行 ROLLBACK,InnoDB 就从 Undo Log 中取出旧版本,把数据恢复到事务开始前的状态,保证原子性(Atomicity)。

  2. MVCC(多版本并发控制) —— 实现一致性读
    当其他事务执行普通 SELECT(快照读)时,会根据 Read View 判断版本可见性:

    • 如果当前版本不可见,就顺着 roll_ptr 去 Undo Log 里找更老的版本。
    • 这就是我们之前讲的“一致性读看到事务开始前的版本”的核心机制。

常见误区纠正

  • Undo Log ≠ 已提交的数据
    Undo Log 存的是历史旧版本(被修改前的数据)。
  • Redo Log 才是记录“修改之后要做什么”的日志(用于崩溃恢复,保证持久性)。
  • 一个事务可能会产生多条 Undo Log(修改多行时),这些 Undo Log 属于同一个事务,但事务提交后,大部分 Undo Log 可以在 purge(清理)阶段被删除(只要没有更老的事务还在使用)。

总结一句话Undo Log 记录的是“每个修改操作发生前的旧数据版本”,而不是 trx_id 对应的提交数据。
它通过版本链 + roll_ptr,为 事务回滚 和 MVCC 一致性读 提供了基础。如果你想更清楚,我可以给你画一个版本链 + Undo Log 的详细图示(带 trx_id 和 roll_ptr 的例子),或者继续解释 purge(Undo Log 清理)机制。