MySQL undo log 和MVCC工作原理

下面通过具体例子完整说明连续INSERT操作的undo log生成形式,以及MVCC如何通过版本控制保持事务隔离性:

一、连续INSERT操作的undo log生成示例

假设存在user表(含idname字段),初始为空。事务A(ID=100)执行以下操作:

BEGIN;  -- 分配事务ID=100
INSERT INTO user (id, name) VALUES (1, '张三');  -- 操作1
INSERT INTO user (id, name) VALUES (2, '李四');  -- 操作2
INSERT INTO user (id, name) VALUES (3, '王五');  -- 操作3
COMMIT;

InnoDB会为每个INSERT操作生成对应的undo log,具体结构如下:

  1. 操作1的undo log:
类型:INSERT
表ID:user表的唯一标识
事务ID:100(生成该记录的事务A的ID)
主键:1(记录的主键值)
删除标记:N(未删除)
undo信息:无(INSERT的undo log仅用于回滚时删除该记录)
  1. 操作2的undo log:
类型:INSERT
表ID:user表的唯一标识
事务ID:100
主键:2
删除标记:N
undo信息:无
  1. 操作3的undo log:
类型:INSERT
表ID:user表的唯一标识
事务ID:100
主键:3
删除标记:N
undo信息:无

特性

  • 这些undo log通过指针串联成链表,便于事务回滚时按顺序执行反向操作(删除插入的记录)。
  • 每条数据记录的隐藏列DB_TRX_ID会被标记为100(创建者事务ID),DB_ROLL_PTR指向对应的undo log。
  • 事务提交后,这些undo log会被标记为可删除,由后台线程定期清理(因为已无需回滚)。

二、MVCC如何通过版本控制保持事务隔离性

以两个并发事务(事务B:ID=200,事务C:ID=300)为例,说明RR(可重复读)隔离级别下的MVCC工作机制:

1. 事务执行时间线与Read View生成

时间点 操作 事务B的Read View(启动时生成) 事务C的Read View(启动时生成)
T1 事务A插入第一条记录(未提交) - -
T2 事务B启动(ID=200) 活跃事务列表:[100]
min_trx_id=100
max_trx_id=201
-
T3 事务B首次查询 (沿用T2的Read View) -
T4 事务A提交所有插入 (Read View不变) -
T5 事务B二次查询 (Read View不变) -
T6 事务B提交,事务C启动(ID=300) - 活跃事务列表:[]
min_trx_id=300
max_trx_id=301
T7 事务C查询 - (沿用T6的Read View)

2. 可见性判断规则与结果

MVCC通过比较记录的DB_TRX_ID(创建事务ID)与当前事务的Read View,判断记录是否可见,规则如下:

  • DB_TRX_ID < min_trx_id:记录在所有活跃事务启动前已提交,可见。
  • DB_TRX_ID >= max_trx_id:记录在当前事务启动后创建,不可见。
  • min_trx_id ≤ DB_TRX_ID < max_trx_id:需检查是否在活跃列表中,在则不可见(事务未提交),不在则可见(事务已提交)。

(1)事务B的查询结果(ID=200)

  • 所有记录的DB_TRX_ID=100,与事务B的Read View对比:
    • 100 ≥ min_trx_id(100)且100 < max_trx_id(201),且100在活跃列表[100]中(事务A在事务B启动时未提交)。
    • 结论:两次查询结果均为空,保持“可重复读”特性(即使事务A已提交,Read View不更新)。

(2)事务C的查询结果(ID=300)

  • 所有记录的DB_TRX_ID=100,与事务C的Read View对比:
    • 100 < min_trx_id(300),说明记录由事务C启动前已提交的事务(A)创建。
    • 结论:查询到3条记录,符合隔离级别的可见性要求。

三、核心总结

  1. undo log作用:为INSERT操作生成回滚凭证(记录需删除的主键),事务提交后可被清理,仅用于异常时回滚。
  2. MVCC核心机制:通过事务启动时生成的Read View(含活跃事务列表、最小/最大事务ID),与记录的DB_TRX_ID对比,控制不同事务对数据版本的可见性。
  3. 隔离性保障:RR级别下Read View不变,确保事务过程中看到一致的数据版本;通过事务ID的单调递增和可见性规则,实现无锁化的隔离控制。
posted @ 2025-08-22 09:10  认真的刻刀  阅读(19)  评论(0)    收藏  举报