MySQL undo log 和MVCC工作原理
下面通过具体例子完整说明连续INSERT操作的undo log生成形式,以及MVCC如何通过版本控制保持事务隔离性:
一、连续INSERT操作的undo log生成示例
假设存在user表(含id和name字段),初始为空。事务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的undo log:
类型:INSERT
表ID:user表的唯一标识
事务ID:100(生成该记录的事务A的ID)
主键:1(记录的主键值)
删除标记:N(未删除)
undo信息:无(INSERT的undo log仅用于回滚时删除该记录)
- 操作2的undo log:
类型:INSERT
表ID:user表的唯一标识
事务ID:100
主键:2
删除标记:N
undo信息:无
- 操作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条记录,符合隔离级别的可见性要求。
三、核心总结
- undo log作用:为INSERT操作生成回滚凭证(记录需删除的主键),事务提交后可被清理,仅用于异常时回滚。
- MVCC核心机制:通过事务启动时生成的Read View(含活跃事务列表、最小/最大事务ID),与记录的
DB_TRX_ID对比,控制不同事务对数据版本的可见性。 - 隔离性保障:RR级别下Read View不变,确保事务过程中看到一致的数据版本;通过事务ID的单调递增和可见性规则,实现无锁化的隔离控制。

浙公网安备 33010602011771号