MySQL 的 MVCC 机制剖析

MVCC 的基本概念

MVCC(Multi-Version Concurrency Control,多版本并发控制)是 MySQL 实现高并发事务处理的核心机制之一。它通过维护数据的多个版本,使读写操作可以并发执行,避免锁竞争,提升数据库性能。

MVCC 在 InnoDB 存储引擎中实现,主要依赖于以下三个关键组件:

  • 隐藏字段:InnoDB 为每行记录添加 DB_TRX_ID(事务 ID)、DB_ROLL_PTR(回滚指针)和 DB_ROW_ID(行 ID)三个隐藏字段。
  • Undo Log:存储数据的历史版本,用于事务回滚和一致性读。
  • ReadView:事务在快照读时生成的视图,用于判断数据版本的可见性。
MVCC 的工作原理

事务的隔离级别与 MVCC
MVCC 主要在 READ COMMITTED(RC)REPEATABLE READ(RR) 隔离级别下发挥作用。不同隔离级别下,ReadView 的生成规则不同:

  • RC 级别:每次执行 SELECT 都会生成新的 ReadView,可能导致不可重复读。
  • RR 级别:仅在第一次 SELECT 时生成 ReadView,后续查询复用该视图,避免不可重复读。

数据版本的可见性判断
ReadView 包含以下关键信息:

  • m_ids:当前活跃事务 ID 列表。
  • min_trx_id:最小活跃事务 ID。
  • max_trx_id:下一个待分配事务 ID。
  • creator_trx_id:创建 ReadView 的事务 ID。

判断规则如下:

  1. 如果记录的 DB_TRX_ID 小于 min_trx_id,说明该版本已提交,可见。
  2. 如果 DB_TRX_ID 大于等于 max_trx_id,说明该版本由未来事务创建,不可见。
  3. 如果 DB_TRX_IDm_ids 中,说明该版本由未提交事务创建,不可见;否则可见。
MVCC 的实现细节

Undo Log 的作用
Undo Log 存储数据的历史版本,通过回滚指针(DB_ROLL_PTR)形成版本链。例如:

-- 假设表 t 初始数据为 (id=1, name='A')
UPDATE t SET name='B' WHERE id=1;
UPDATE t SET name='C' WHERE id=1;

此时版本链为:C ← B ← A,通过回滚指针可追溯历史版本。

快照读与当前读

  • 快照读:普通 SELECT 语句,基于 ReadView 读取可见版本。
  • 当前读:加锁的 SELECT(如 SELECT ... FOR UPDATE)、UPDATE、DELETE 等操作,直接读取最新数据。
MVCC 的优缺点

优点

  • 读写不冲突,提高并发性能。
  • 避免脏读和不可重复读(RR 级别)。

缺点

  • 需要维护多版本数据,占用额外存储空间。
  • 无法解决幻读问题(RR 级别下需配合间隙锁)。
案例分析

场景:事务并发读写
事务 A(ID=100)和事务 B(ID=200)同时操作同一行数据:

  1. 事务 A 更新数据,生成新版本并写入 Undo Log。
  2. 事务 B 发起快照读,根据 ReadView 判断是否可见事务 A 的修改。

若事务 B 的 ReadView 在事务 A 提交前生成,则看不到 A 的修改;否则可见。

总结

MVCC 是 MySQL 实现高并发的关键技术,通过多版本和 ReadView 机制平衡一致性与性能。理解其原理有助于优化事务设计和排查并发问题。

https://github.com/miladschul/z3g_n2g9
https://github.com/orrazarz/8rh_exo8
https://github.com/chincairo/gkd_4g9a
https://github.com/sangpathac/r3c_ks9l
https://github.com/emarrona/cuk_1zgc

Logo

这里是“一人公司”的成长家园。我们提供从产品曝光、技术变现到法律财税的全栈内容,并连接云服务、办公空间等稀缺资源,助你专注创造,无忧运营。

更多推荐