MySQL MVCC 实现原理详解

5次阅读

MySQL MVCC 实现原理详解

什么是 MVCC

MVCC(Multi-Version Concurrency Control,多版本并发控制)是 InnoDB 存储引擎实现高并发读写的核心机制。它不依赖传统锁来解决读-写冲突,而是通过为每行数据维护多个历史版本,让不同事务能各自看到符合其隔离级别要求的一致性快照。简单说,就是“读不阻塞写,写不阻塞读”——读操作拿的是过去某个时间点的快照,写操作更新的是新版本,互不影响。

关键组件:隐藏字段、Undo Log 和 Read View

MVCC 的落地依赖三个底层支撑:

  • 隐藏字段:InnoDB 自动为每行记录添加三个系统列:
    DB_TRX_ID:记录最后一次修改该行的事务 ID;
    DB_ROLL_PTR:回滚指针,指向该行上一个历史版本(存于 Undo Log 中);
    DB_ROW_ID:隐式主键,用于生成聚簇索引(当表无主键时)。
  • Undo Log:每次 UPDATE 或 delete 前,旧版本数据被写入 Undo Log,并通过 DB_ROLL_PTR 连成一条“版本链”。这条链从最新记录开始,可逐级回溯到任意历史状态。
  • Read View:事务执行快照读时生成的“可见性快照”,包含当时活跃事务 ID 列表、最小未提交事务 ID(min_id)、最大已分配事务 ID(max_id)。它决定哪些版本对当前事务可见。

快照读 vs 当前读

mysql 将读操作明确分为两类:

  • 快照读(Snapshot Read):普通 select,不加锁,读取的是基于 Read View 的一致性版本。在 可重复读(RR) 隔离级别下,事务内首次查询生成 Read View 后全程复用;在 读已提交(RC) 下,每次查询都新建 Read View。
  • 当前读(Current Read):带锁读或写操作,如 SELECT … for UPDATEUPDATEDELETEINSERT。它们总是读取最新已提交版本,并加行锁(共享锁或排他锁),确保数据不被其他事务并发修改。

可见性判断逻辑

当执行快照读时,InnoDB 沿着版本链从最新记录开始,逐条比对每版的 DB_TRX_ID 与当前事务的 Read View:

  • 若版本的 trx_id → 属于已提交事务,可见;
  • 若版本的 trx_id > max_id → 属于未来事务,不可见;
  • 若版本的 trx_id 在活跃事务数组中 → 正在运行未提交,不可见;
  • 若版本的 trx_id 落在 [min_id, max_id) 且不在活跃数组中 → 已提交,可见。

找到第一个满足条件的版本,即为本次查询返回的结果。

text=ZqhQzanResources