1. 什么是MVCC?
MVCC(Multi-Version Concurrency Control,多版本并发控制) 是 MySQL(InnoDB引擎)实现高并发访问的核心机制之一。它通过在同一时刻保存数据的多个版本,使得:
- 读操作不阻塞写操作
- 写操作不阻塞读操作
- 提高数据库的并发性能
📌 对比锁机制:
- 传统锁(如行锁)会导致读写冲突
- MVCC 通过数据多版本实现非阻塞读
2. MVCC 核心原理
2.1 版本链与隐藏字段
InnoDB 每行记录包含3个隐藏字段:
- DB_TRX_ID(6字节):最近修改该行的事务ID
- DB_ROLL_PTR(7字节):回滚指针,指向Undo Log中的旧版本
- DB_ROW_ID(6字节):行ID(无主键时自动生成)
-- 实际存储结构(伪代码)
row = {
id: 1,
name: "Alice",
DB_TRX_ID: 100,
DB_ROLL_PTR: 0x123456,
DB_ROW_ID: 1
}
2.2 Undo Log(回滚日志)
- 存储数据被修改前的历史版本,形成版本链
- 用于:
- 事务回滚(ROLLBACK)
- MVCC 读一致性视图
2.3 ReadView(一致性视图)
决定事务能看到哪个版本的数据,包含:
- creator_trx_id:创建该ReadView的事务ID
- m_ids:生成ReadView时活跃的事务ID列表
- min_trx_id:m_ids中的最小ID
- max_trx_id:系统下一个待分配的事务ID
3. MVCC 工作流程
3.1 读操作(SELECT)
通过 ReadView 判断数据可见性:
- 如果
DB_TRX_ID < min_trx_id
:说明数据在ReadView创建前已提交 → 可见 - 如果
DB_TRX_ID >= max_trx_id
:说明数据在ReadView创建后修改 → 不可见 - 如果
min_trx_id <= DB_TRX_ID < max_trx_id
:- 若
DB_TRX_ID ∈ m_ids
:说明事务未提交 → 不可见 - 否则 → 可见
- 若
3.2 写操作(UPDATE/DELETE)
- 新数据写入时,旧数据进入 Undo Log
- 更新
DB_TRX_ID
为当前事务ID - 更新
DB_ROLL_PTR
指向旧版本
4. MVCC 与隔离级别
不同隔离级别下 MVCC 的行为:
隔离级别 | MVCC 行为 |
---|---|
READ UNCOMMITTED | 直接读最新数据(不适用MVCC) |
READ COMMITTED (RC) | 每次SELECT生成新ReadView,能看到其他事务已提交的修改 |
REPEATABLE READ (RR) | 第一次SELECT时生成ReadView,后续沿用该视图(避免不可重复读) |
SERIALIZABLE | 退化为加锁(不适用MVCC) |
5. 实战案例分析
场景:事务并发修改同一条数据
-- 初始数据
INSERT INTO users (id, name) VALUES (1, 'Alice');
-- 事务1(TRX_ID=100)
BEGIN;
UPDATE users SET name = 'Bob' WHERE id = 1;
-- 事务2(TRX_ID=200,在RC隔离级别下)
BEGIN;
SELECT name FROM users WHERE id = 1; -- 看到 'Alice'(ReadView在事务1提交前生成)
COMMIT;
-- 事务1提交后
COMMIT;
-- 事务3(TRX_ID=300)
BEGIN;
SELECT name FROM users WHERE id = 1; -- 看到 'Bob'(事务1已提交)
6. MVCC 的优缺点
优点
✅ 高并发:读写不互相阻塞
✅ 避免锁竞争:减少死锁概率
✅ 快照读:支持一致性非锁定读
缺点
❌ 额外存储:需维护Undo Log和历史版本
❌ 清理成本:需要Purge线程清理旧版本数据
7. 关键参数优化
-- 查看InnoDB MVCC相关状态
SHOW ENGINE INNODB STATUS;
-- 控制Undo Log保留时间(默认0,表示由purge线程自动管理)
SET GLOBAL innodb_undo_log_truncate = ON;
SET GLOBAL innodb_undo_retention = 3600; -- 保留1小时
总结
- MVCC 通过版本链 + ReadView 实现非阻塞读
- RC/RR 隔离级别依赖 MVCC 实现不同的一致性视图
- Undo Log 是 MVCC 的基石,存储历史版本数据
- 合理设置隔离级别和undo保留时间可优化性能
理解 MVCC 能帮助你设计更高并发的数据库应用! 🚀