undo log 回滚原理

MySQL 的 Undo Log(回滚日志)是实现事务回滚和多版本并发控制(MVCC)的核心机制。它记录了事务对数据修改前的原始状态,确保事务可以按需回滚到之前的状态。以下是 Undo Log 实现事务回滚的详细流程和原理:


1. Undo Log 的作用

  • 事务回滚:回滚未提交事务的修改。
  • MVCC:提供历史数据版本,支持非锁定读(如 SELECT 查询读取快照)。
  • 崩溃恢复:辅助恢复未提交事务的修改。

2. Undo Log 的结构

每条 Undo Log 记录包含以下关键信息:

  • 事务 ID(TRX_ID):标识生成该记录的事务。
  • 回滚指针(ROLL_PTR):指向更早版本的 Undo Log 记录,形成版本链。
  • 修改前的数据镜像:被修改前的数据值(旧值)。
  • 操作类型:标识操作是 INSERTUPDATE 还是 DELETE

不同类型的 Undo Log

操作类型 Undo Log 内容 回滚行为
INSERT 记录新插入行的主键值。 回滚时根据主键删除该行。
UPDATE 记录被修改前的旧值(包括所有字段)。 回滚时将数据恢复为旧值。
DELETE 记录被删除行的完整内容(所有字段值)。 回滚时重新插入该行。

3. 事务回滚的流程

步骤 1:生成 Undo Log

  • 事务执行 INSERT/UPDATE/DELETE 操作时,InnoDB 会先写 Undo Log,再修改内存中的数据页。
  • 例如:
    UPDATE users SET name = 'Alice' WHERE id = 1;
    
    修改前,Undo Log 会记录 id=1 的原值(如 name='Bob')。

步骤 2:构建版本链

  • 同一行数据的多次修改会形成 Undo Log 版本链,通过 ROLL_PTR 指针串联。
    当前行数据 → Undo Log 1(最新修改) → Undo Log 2(更早修改) → ...
    

步骤 3:触发回滚

  • 当事务执行 ROLLBACK 或因异常终止时,InnoDB 会根据事务 ID 找到其所有 Undo Log 记录。
  • 逆向应用 Undo Log:从最新操作开始,按操作逆序执行回滚:
    • 如果是 UPDATE,将数据恢复为旧值。
    • 如果是 DELETE,重新插入被删除的行。
    • 如果是 INSERT,删除新插入的行。

步骤 4:清理 Undo Log

  • 已提交事务的 Undo Log 不会立即删除,可能被 MVCC 或未提交事务引用。
  • 当所有依赖该 Undo Log 的事务结束后,由后台线程(Purge Thread)清理无用的 Undo Log。

4. 示例:UPDATE 操作的回滚

假设事务 A 执行以下操作:

-- 原始数据:id=1, name='Bob', age=20
UPDATE users SET name = 'Alice' WHERE id = 1;
UPDATE users SET age = 25 WHERE id = 1;
COMMIT;

若事务 A 在提交前回滚:

  1. 逆向处理第二条 UPDATE:将 age=25 恢复为 age=20
  2. 逆向处理第一条 UPDATE:将 name='Alice' 恢复为 name='Bob'

5. Undo Log 的存储与管理

  • 存储位置:Undo Log 存储在 回滚段(Rollback Segments) 中,每个回滚段包含多个 Undo Slot。
  • 持久化:Undo Log 写入磁盘的 undo tablespace(默认文件为 undo_001undo_002),但写入时仅追加到内存的 Undo Buffer,异步刷盘。
  • 崩溃恢复:数据库重启时,通过 Redo Log 恢复 Undo Log,再根据 Undo Log 回滚未提交的事务。

6. Undo Log 与 MVCC

除了回滚,Undo Log 还支持 MVCC:

  • 当一个事务执行 SELECT 查询时,会基于当前活跃事务 ID 列表,通过 Undo Log 版本链找到可见的旧版本数据(快照读),避免阻塞写操作。

7. 关键参数优化

  • innodb_undo_tablespaces:设置 Undo Log 表空间数量(默认 2)。
  • innodb_max_undo_log_size:单个 Undo 表空间的最大大小(默认 1GB)。
  • innodb_undo_log_truncate:启用自动清理 Undo Log 空间(避免膨胀)。

总结

  • Undo Log 是事务原子性的基石:通过记录旧值,确保事务可以回滚到修改前的状态。
  • 回滚流程:逆向应用 Undo Log,按操作类型恢复数据。
  • 与 MVCC 协同:支持非锁定读,提升并发性能。
  • 设计权衡:Undo Log 需要平衡空间占用、性能开销和一致性要求。

results matching ""

    No results matching ""