多版本并发控制
多版本并发控制(MVCC,Multi-Version Concurrency Control)是一种实现高并发事务隔离的核心机制。它通过保存数据的多个历史版本,让读写操作不堵塞,从而避免了传统锁机制带来的瓶颈。
1. 核心思想
MVCC 为每个事务提供一个数据快照(Snapshot),事务读取的是某个时间点的一致性数据版本,而不是最新的数据,如此一来:
-
读操作不需要等待写操作释放锁
-
写操作也不需要等待读操作完成
-
实现了非阻塞读
2. 关键数据结构
InnoDB通过Undo Log + 隐藏字段 + Read View实现MVCC。
2.1 Undo Log
Undo Log是 MVCC 的版本链基础:
-
插入:
undo log记录主键,用于回滚时删除 -
删除:标记删除,
undo log记录完整行数据,用于恢复 -
更新:
undo log记录旧值,形成版本链
2.2 隐藏字段
每行记录自动添加,对用户不可见,
InnoDB自动维护
| 字段名 | 大小 | 作用 |
|---|---|---|
DB_TRX_ID | 6 字节 | 创建该版本的事务ID(最后修改此行的事务) |
DB_ROLL_PTR | 7 字节 | 回滚指针,指向undo log的上一个版本 |
DB_ROW_ID | 6 字节 | 隐藏主键 |
2.3 Read View
Read View是事务执行快照读时生成的一致性试图,决定事务能看待哪些版本的数据。
Read View包含的关键字段:
| 字段 | 说明 |
|---|---|
creator_trx_id | 创建该Read View的事务ID |
m_ids | 生成Read View时,活跃(未提交)事务ID列表 |
min_trx_id | m_ids中的最小值 |
max_trx_id | 生成Read View时,系统分配的下一个事务ID(全局最大加 1) |
3. 可见性判断规则
当事务读取某行数据时,通过比较该行的DB_TRX_ID与Read View来判断可见性:
判断流程(对版本链从上到下遍历):
1. 如果 DB_TRX_ID == creator_trx_id → 可见(自己修改的)
2. 如果 DB_TRX_ID < min_trx_id → 可见(已提交事务修改的)
3. 如果 DB_TRX_ID >= max_trx_id → 不可见(将来事务修改的,未发生)
4. 如果 min_trx_id <= DB_TRX_ID < max_trx_id:
- 如果 DB_TRX_ID 在 m_ids 中 → 不可见(未提交事务修改的)
- 如果 DB_TRX_ID 不在 m_ids 中 → 可见(已提交事务修改的)
如果不可见,就沿着 DB_ROLL_PTR 找上一个版本,重复判断。
4. 两种读操作
| 读类型 | 说明 | 实现方式 |
|---|---|---|
| 快照读(Snapshot Read) | 不加锁,读取历史版本 | 基于 MVCC + Read View |
| 当前读(Current Read) | 读取最新版本,需要加锁 | SELECT ... FOR UPDATE/ DML 语句 |
只有普通
SELECT是快照读,其他操作(UPDATE、DELETE等)都是当前读,需要加锁
5. 与事务隔离级别的关系
| 隔离级别 | MVCC 行为 |
|---|---|
READ UNCOMMITED | 不适用 MVCC,直接读最新版本(可能脏读) |
READ COMMITED | 每次SELECT都生成新的Read View,能看到其他事务已提交的最新修改 |
REPEATABLE READ | 事务开始时生成一个Read View,整个事务复用,保证可重复读 |
SERIALIZABLE | 不使用 MVCC,所有操作加锁 |
MySQL 默认隔离级别为
REPEATABLE READ
&spm=1001.2101.3001.5002&articleId=163134434&d=1&t=3&u=9f8ec409554645da9e5b29f57cc5331f)
2534

被折叠的 条评论
为什么被折叠?



