MVCC(Multi-Version Concurrency Control,多版本并发控制)是MySQL实现并发控制的核心机制之一,它使得InnoDB存储引擎在保证一定隔离级别的同时,能够提供高性能的读写并发。
一、MVCC基本概念
MVCC是一种通过数据多版本来实现并发控制的机制,其核心思想是:
- 保存数据的历史版本
- 通过比较版本号来决定数据是否对当前事务可见
- 读操作不加锁,写操作只锁定必要的行
二、MVCC实现的关键要素
1. 隐藏字段
InnoDB每行记录都包含几个隐藏字段:
- `DB_TRX_ID`(6字节):记录最近修改该行数据的事务ID
- `DB_ROLL_PTR`(7字节):回滚指针,指向该行的undo log记录
- `DB_ROW_ID`(6字节):隐藏的自增ID(如果没有主键时)
2. Undo Log
- 存储数据被修改前的值
- 用于事务回滚和MVCC读取历史版本
- 形成版本链,通过`DB_ROLL_PTR`指针连接
3. Read View
决定事务能看到哪些版本的数据,包含:
- `m_ids`:当前活跃(未提交)的事务ID列表
- `min_trx_id`:m_ids中的最小值
- `max_trx_id`:系统应该分配给下一个事务的ID
- `creator_trx_id`:创建该Read View的事务ID
三、MVCC工作原理
1. 数据读取流程
当执行SELECT操作时:
1. 获取当前事务的Read View
2. 遍历行记录的版本链(通过undo log)
3. 检查每行版本的`DB_TRX_ID`:
- 如果`DB_TRX_ID` < `min_trx_id`:可见
- 如果`DB_TRX_ID` > `max_trx_id`:不可见
- 如果`min_trx_id` ≤ `DB_TRX_ID` ≤ `max_trx_id`:
- 如果`DB_TRX_ID`在`m_ids`中:不可见(事务未提交)
- 否则:可见
4. 返回第一个可见版本的数据
2. 数据修改流程
当执行UPDATE/DELETE操作时:
1. 获取行记录的排他锁(X锁)
2. 记录undo log
3. 修改行数据,更新`DB_TRX_ID`为当前事务ID
4. 将`DB_ROLL_PTR`指向undo log记录
四、MVCC与隔离级别
1. READ COMMITTED (RC)
- 每次读取前都生成新的Read View
- 能看到其他事务已提交的修改
- 可能出现不可重复读问题
2. REPEATABLE READ (RR)
- 只在第一次读取时生成Read View
- 使用同一Read View完成整个事务
- 解决不可重复读问题(MySQL通过MVCC+间隙锁解决幻读)
五、MVCC的优势与限制
优势:
1. 读不加锁,读写不冲突,提高并发性能
2. 避免脏读、不可重复读问题
3. 减少死锁概率
限制:
1. 需要额外存储空间(undo log)
2. 需要维护版本链,增加维护成本
3. 长期运行的事务可能导致undo log膨胀
六、MVCC与Purge机制
为了防止undo log无限增长,InnoDB有purge线程:
1. 删除不再需要的undo log
2. 清理已提交事务不再需要的旧版本数据
3. 基于系统中最老Read View判断哪些版本可清理
七、实际案例分析
场景:事务并发读取
``` 事务A(trx_id=100) 事务B(trx_id=101) BEGIN; BEGIN; SELECT * FROM t; UPDATE t SET c1=20 WHERE id=1; COMMIT; SELECT * FROM t; ```
在RR级别下:
- 事务A的两次SELECT使用同一个Read View
- 事务B的修改对事务A不可见
- 保证可重复读
八、总结
MVCC是MySQL实现高并发的重要机制,通过版本控制和Read View实现了:
- 读不加锁,提高并发性能
- 支持RC和RR隔离级别
- 避免常见的并发问题
0条评论
点击登录参与评论