MVCC 机制(RC / RR 的真正区别)

🧨 先一句话总纲:

RC 每次 SELECT 都重新生成 ReadView(看最新已提交)
RR 一个事务只生成一次 ReadView(看固定快照)

区别就这一个点。
所有连锁反应,包括“不可重复读”怎么来的,都从这里推出来,简单清晰。


🔥 1. MVCC 是怎么实现的(版本链动画)

InnoDB 在每行加两个隐藏字段:

trx_id        # 最新更新这行的事务ID
roll_pointer  # 指向 undo log(老版本记录)

用这些 Undo 一条条串起来,就形成 “版本链”:

最新版本 → 上一版本 → 再上一版本 → ...
     trx_id=20       trx_id=15       trx_id=8

🎬 2. ReadView 是 MVCC 的灵魂

ReadView 本质是一张“我能看到哪些事务的提交”的白名单。

包含 4 个关键字段:

m_ids:当前未提交事务ID集合
min_trx_id
max_trx_id
creator_trx_id

你不需要死记这些字段,只要知道:

关键逻辑:

当一个事务在读一行时,InnoDB 会从版本链里往上找:

找第一个 “我有权限读取” 的版本

权限判断规则非常简单:

  • 版本的 trx_id 已提交 → ✔ 可读
  • 版本的 trx_id 未提交 → ❌ 跳过
  • 版本的 trx_id 是自己事务 → ✔ 可读

🧨 3. RC 与 RR 差异:关键是 ReadView 何时生成

这个点你一定要牢牢抓住:

⭐ RC(Read Committed)

每次 SELECT 都重新生成 ReadView

意味着:

同一个事务中的两次 SELECT 看到的数据可能不一样

这导致:

  • 不可重复读(Non-repeatable read)

⭐ RR(Repeatable Read)

整个事务只在第一次 SELECT 时生成 ReadView
之后所有 SELECT 都用第一次的 ReadView。

意味着:

同一个事务的所有查询看到的都是“同一个快照”

这确保:

  • 可重复读(Repeatable read)

👇 这个动画能让你瞬间懂区别

假设有一行记录:

id=1, age=18

你开启事务 T1:

SET tx_isolation='READ-COMMITTED'; -- RC
BEGIN;
SELECT age FROM user WHERE id=1;

这时 ReadView1 = [记录当前活跃事务]


这时另一个事务 T2 来更新并提交:

UPDATE user SET age=20 WHERE id=1;
COMMIT;

⭐ 现在 T1 再查一次(RC 下):

SELECT age FROM user WHERE id=1;

因为 RC 每次 SELECT 都生成新的 ReadView2,所以:

第一次看到年龄=18
第二次看到年龄=20

就是“不一致”,这就是 不可重复读


⭐ 那在 RR 下会怎样?

RR 在事务开始/第一次 SELECT 时创建 ReadView,之后都不会变。

即使 T2 已经提交,T1 仍然只能看到旧版本:

第一次看到 18
第二次仍然看到 18
第三次也看到 18

这就是 Repeatable Read。


🧩 所以 RC 与 RR 的本质差异一句话总结:

RC:每次读都看“最新提交的版本”
RR:整个事务都看“自己第一次看见的快照”

🧠 为什么 RR 能解决不可重复读?

因为:

  • ReadView 不变 → 你读的范围不变 → 看不到别人提交的更新

🔥 那 RR 能防幻读吗?(经典误区)

答案:InnoDB 的 RR + 间隙锁 = 可以防大部分幻读,但靠的是锁,不是 MVCC。

MVCC 本身不能防幻读。
原因很简单:

MVCC 只解决旧版本的问题
幻读是新插入了一行,这行根本没有旧版本

所以 InnoDB 使用 Gap Lock(间隙锁)来解决这个问题。

例如:

SELECT * FROM user WHERE age BETWEEN 10 AND 30 FOR UPDATE;

会锁住对应范围的间隙,别人无法插入 age 在这个区间的新行。


🧨 核心结论图(你面试直接说这个就够了)

                    RC                 RR
ReadView 生成      每次 SELECT        第一次 SELECT
可重复读           ❌ 不保证          ✔ 保证
不可重复读         ✔ 存在            ❌ 避免
幻读               ✔ 存在            ✔ 基本避免(靠锁)
MVCC 使用方式      读旧版本           读固定快照
posted @ 2025-12-06 14:38  中登程序猿  阅读(0)  评论(0)    收藏  举报