InnoDB MVCC 快照读与当前读的区别及 RC/RR 下的表现

举报
yd_220030742 发表于 2026/10/23 09:14:15 2026/10/23
【摘要】 背景InnoDB 通过多版本并发控制(MVCC)实现读写不互相阻塞:普通的 SELECT 读取的是数据的某个历史快照,而加锁读和写操作读取的是最新已提交的数据。理解快照读与当前读的区别,以及它们在 READ COMMITTED(RC)与 REPEATABLE READ(RR)隔离级别下的表现,有助于分析幻读、不可重复读等问题。 隐藏列与 undo 版本链InnoDB 聚簇索引记录包含隐藏列...

背景

InnoDB 通过多版本并发控制(MVCC)实现读写不互相阻塞:普通的 SELECT 读取的是数据的某个历史快照,而加锁读和写操作读取的是最新已提交的数据。理解快照读与当前读的区别,以及它们在 READ COMMITTED(RC)与 REPEATABLE READ(RR)隔离级别下的表现,有助于分析幻读、不可重复读等问题。

隐藏列与 undo 版本链

InnoDB 聚簇索引记录包含隐藏列:DB_TRX_ID 记录最近一次修改该行的事务 ID,DB_ROLL_PTR 指向 undo log 中该行的上一个版本,没有显式主键时还会有 DB_ROW_ID。每次更新都会把旧版本写入 undo log,并通过 DB_ROLL_PTR 串成版本链,链头是最新版本。

Read View 可见性规则

Read View 在创建时记录:m_ids(当前活跃的读写事务 ID 列表)、min_trx_id(活跃事务中最小的 ID)、max_trx_id(下一个将分配的事务 ID)、creator_trx_id(创建者自身事务 ID)。判断某个版本的 DB_TRX_ID 是否可见:等于 creator_trx_id 则可见(自己的修改);小于 min_trx_id 则可见(生成前已提交);大于等于 max_trx_id 则不可见;介于两者之间时,若在 m_ids 中则不可见,否则可见。不可见时沿 undo 版本链继续向前查找,直到找到可见版本。

RC 与 RR 的差异

差别在于 Read View 的创建时机。RC 下每次执行快照读都会生成新的 Read View,因此能读到其他事务刚提交的数据,出现不可重复读。RR 下事务中第一次快照读时创建 Read View 并一直复用,因此同一事务内多次普通查询结果一致。示例(表 t(id PK, v),初始 id=1, v=10):

-- 会话 A
BEGIN;
SELECT v FROM t WHERE id=1;  -- 返回 10
-- 会话 B
BEGIN;
UPDATE t SET v=20 WHERE id=1;
COMMIT;
-- 会话 A
SELECT v FROM t WHERE id=1;  -- RC 返回 20,RR 仍返回 10

快照读 vs 当前读(SELECT … FOR UPDATE / UPDATE)

快照读指不加锁的普通 SELECT,依据 Read View 读取可见版本。当前读包括 SELECT … FOR UPDATE、SELECT … LOCK IN SHARE MODE、UPDATE、DELETE、INSERT,它们总是读取记录的最新已提交版本,并加上相应的行锁(RR 下还可能加间隙锁以防止幻读)。接上例,在 RR 下会话 A 再执行 SELECT v FROM t WHERE id=1 FOR UPDATE 将返回 20;若执行 UPDATE t SET v=v+1 WHERE id=1,则基于最新值 20 更新为 21,之后会话 A 的快照读也能看到自己修改的结果 21。这也是 RR 下同一事务中快照读与当前读结果可能不一致的原因。

小结

MVCC 依靠隐藏列、undo 版本链和 Read View 实现一致性非锁定读。RC 每次快照读都新建 Read View,RR 则在首次快照读时创建并复用;当前读始终读取最新数据并加锁。业务中如需基于最新数据做判断和修改,应使用当前读,而不是依赖快照读的结果。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。