解释一下mvcc

31 阅读2分钟

MVCC(Multi-Version Concurrency Control,多版本并发控制)一句话解释:

通过为同一行数据保存多个版本,让“读”操作读历史快照,“写”操作生成新版本,从而实现读写不互相阻塞

它是 InnoDB 高并发、低锁冲突的核心机制。


一、要解决什么问题?

传统锁模型:

读要加锁,写要加锁
→ 读写互相阻塞,性能差

MVCC 的思路:

写:产生新版本
读:读旧版本(快照)
→ 读不阻塞写,写不阻塞读

二、InnoDB 里 MVCC 的核心组成

每一行记录都有隐藏字段:

  1. trx_id:最后修改该行的事务 ID
  2. roll_pointer:指向 Undo Log 中的上一个版本
  3. Undo Log:保存历史版本(形成版本链)
  4. Read View:当前事务的可见性快照规则

结构示意:

最新行 (trx_id=100)
   ↓ roll_pointer
旧版本 (trx_id=90)
   ↓
更旧版本 (trx_id=80)

三、Read View 是什么?

Read View 是事务启动时生成的一个“可见性规则表”,包含:

  • m_ids:当前活跃事务ID列表
  • min_trx_id:最小活跃事务ID
  • max_trx_id:下一个将分配的事务ID

判断一行数据是否可见的规则:

  1. trx_id < min_trx_id → 可见(老事务)
  2. trx_id > max_trx_id → 不可见(未来事务)
  3. trx_id 在 m_ids 中 → 不可见(未提交)
  4. 其他 → 可见

如果当前版本不可见,就沿着 Undo Log 找旧版本。


四、RC 与 RR 隔离级别下的差异

隔离级别Read View 生成时机现象
Read Committed每次 SELECT 都生成可能不可重复读
Repeatable Read事务第一次 SELECT 生成一次可重复读(InnoDB 默认)

五、MVCC 与锁的关系

MVCC 解决的是:

  • 普通快照读SELECT

以下仍然要加锁:

  • 当前读:

    SELECT ... FOR UPDATE
    SELECT ... LOCK IN SHARE MODE
    UPDATE / DELETE
    

这些走的是行锁 + 间隙锁,而不是 MVCC。


六、面试级一句话总结

MVCC 是通过在每行记录中维护事务版本号和 Undo Log 版本链,并结合 Read View 可见性规则,使读操作可以读取历史快照版本,从而实现读写不加锁、写写加锁的并发控制机制,是 InnoDB 实现高并发与事务隔离的核心原理。