mysql-mvcc

7 阅读4分钟

一次彻底搞懂 MySQL MVCC:从“快照”到“可见性”的完整思维链路

在我真正理解 MySQL MVCC 之前,总觉得“多版本控制”像个虚的概念。直到自己顺着“普通 SELECT 也有事务”这条线往下挖,才发现 MVCC 的世界比想象的更精巧。下面是我理清思路后的完整笔记,帮你在脑中构建一个能动起来的 MVCC 模型。


一、从一个问题开始:普通 SELECT 也有事务?

很多人以为只有显式的 BEGIN...COMMIT 才是事务,其实 任何 SQL 语句都会在事务上下文中执行

即使是一条最简单的 SELECT,InnoDB 也会隐式地执行:

开启事务 → 创建快照(Read View) → 查询 → 自动提交

也就是说,每一次查询其实都发生在“某个时间点的世界里”。

这个快照不是复制一份数据,而是一份逻辑视图,用来决定哪些版本对当前事务可见。

要点:****

  • SELECT 也在事务中执行,只是自动开启自动提交。
  • “快照”是逻辑概念,不是整表副本。
  • 一切可见性判断都依赖于事务。

二、MVCC 的核心:多版本行可见性

MVCC 全称 Multi-Version Concurrency Control,直译是“多版本并发控制”。

它解决的核心问题是:在高并发读写下,如何既不加锁又能读到一致的数据。****

当上千个事务同时修改同一张表时,每条记录其实不止一个版本。

InnoDB 通过三类隐藏字段来维护这些版本信息:

字段含义
DB_TRX_ID最近修改该行的事务 ID
DB_ROLL_PTR指向旧版本(Undo 日志)的指针
DB_ROW_ID当表没有主键时的系统行号

当你执行查询时,InnoDB 并不会直接返回“当前页上的最新值”,而是通过“可见性判断”来决定该返回哪个版本。


三、可见性判断:数据库的时间旅行器

查询一行数据时,InnoDB 会将当前行的 DB_TRX_ID 与事务快照(Read View)进行比较。

快照里保存了:

  • 当前活跃事务列表;

  • 最大已分配事务 ID(上界);

  • 当前事务 ID。

判断逻辑可以简化为:

flowchart TD
  A[读取行版本] --> B{该版本在快照前已提交?}
  B -- 是 --> C[可见 返回该版本]
  B -- 否 --> D{是否存在 Undo 旧版本?}
  D -- 是 --> E[沿 Roll Pointer 取旧版本 重试]
  D -- 否 --> F[不可见 此行在快照中不存在]

这套机制就像“时间旅行”:

你拿着一张“快照通行证”,在时间博物馆里浏览展品。

每件展品都有时间戳和修改记录,系统会根据你的通行证判断:

“这件东西在你进入之前就存在吗?如果不是,请看它的旧版本。”

要点:****

  • 快照决定“你能看到哪些事务的结果”;
  • 行的隐藏字段决定“这个版本属于谁”;
  • 可见性判断将两者结合,实现真正的多版本控制。

四、Undo 日志与版本链:回到过去的通道

每次 UPDATE 或 DELETE,旧版本都会被写入 Undo 日志。

DB_ROLL_PTR 就像一条回溯指针,串起了整条“版本链”。

查询时,如果当前版本对事务不可见,就沿着这条链回退,直到找到一个符合快照条件的版本。

而当没有任何事务再需要旧版本时,后台 Purge 线程 会清理这些历史数据。

要点:****

  • Undo 是历史版本仓库。
  • Roll Pointer 串起版本链。
  • Purge 清理不再需要的历史版本。

五、隔离级别下的快照时机

不同隔离级别下,Read View 的创建时机不同:

隔离级别快照创建时机读到的效果
REPEATABLE READ第一次一致性读时创建,事务内复用同一事务多次 SELECT 结果一致
READ COMMITTED每次一致性读都新建快照能看到其他事务新提交的数据

提醒:****

  • 两者都不会产生脏读。
  • 区别仅在于快照的“生命周期”。

六、遗漏与轻度补全

你的笔记几乎涵盖了 MVCC 的关键流程,这里补一个常被忽略的点:

“锁定读”不使用快照。

像 SELECT ... FOR UPDATE、LOCK IN SHARE MODE 这类查询,会直接加锁读取最新数据,不走一致性读路径。


七、总结复盘:四个记忆钉

  1. 每个查询都有事务,即使是自动提交模式。

  2. 快照是事务级视图,不是物理副本。

  3. 行的隐藏字段 + Undo 构成版本链,Read View 决定可见性。

  4. 高并发靠“版本可见性”维持一致性,而非靠加锁。

学会从“时间旅行”的角度看待 InnoDB,每一条 SELECT 都是一次穿越:

去看一个时间点上,对你而言“存在”的世界。