连载中 8/22

隔离级别与 MVCC:快照读到底读的是什么

2026-05-05 · 6687 阅读 · 0 评论 · 0 赞

三个经典怪象

老王的对账脚本最近天天出鬼:同一个事务里两次查询余额,数字不一样;运营报表里偶尔出现一条取消事务里「没存在过」的订单;还有对账统计偶尔多算一笔。三个怪象,正好对应事务并发的三大问题:脏读、不可重复读、幻读。这篇把隔离级别和 MVCC 讲透,怪象自然消解。

三大并发问题与四个级别

问题现象
脏读读到了别的事务还没提交的数据,对方回滚后这就是幻觉数据
不可重复读同一事务内两次读同一行,值变了(别人提交了 update)
幻读同一事务内两次按相同范围查询,行数变了(别人提交了 insert)

SQL 标准给出四个隔离级别,隔离性依次增强、并发性能依次减弱:

级别脏读不可重复读幻读
读未提交 RU可能可能可能
读已提交 RC杜绝可能可能
可重复读 RR(InnoDB 默认)杜绝杜绝快照读杜绝
串行化杜绝杜绝杜绝

注意 MySQL 的 RR 对幻读的表述是「快照读下杜绝」——当前读场景要靠间隙锁,这是第 9 篇的话题,这里先埋一句。

MVCC 的骨架:版本链

InnoDB 的每行记录都有两个隐藏列:trx_id(最后修改它的事务 ID)和 roll_pointer(指向上一个版本的指针)。每次 update 都把旧版本压进 undo log,用 roll_pointer 串成一条版本链——第 7 篇说的 undo 第二职责,就是这条链。

ReadView:给可见性画一条线

事务读数据时生成一个 ReadView,核心四个字段:当前活跃(未提交)事务 ID 列表 m_ids、其中最小的 min_trx_id、下一个将分配的事务 ID max_trx_id、自己的 creator_trx_id。拿到一个版本,判断规则四条:

  • 版本的 trx_id == 自己 → 自己改的,可见;
  • trx_id < min_trx_id → 改它的事务早已提交,可见;
  • trx_id >= max_trx_id → 改它的事务在我快照之后才开始,不可见;
  • 在两者之间 → 查 m_ids:还活跃着(没提交)不可见,已提交可见。

当前版本不可见,就顺 roll_pointer 找上一版本再判断——直到找到第一个可见版本。所谓快照读,就是「顺着版本链找出对我可见的那个版本」。

RC 和 RR 的唯一区别

就一条:RC 每次执行查询都生成新的 ReadView;RR 只在事务第一次读时生成一个,整个事务复用。RR 复用同一份快照,所以两次读同一行结果必然相同(不可重复读被杜绝);RC 每次看最新已提交版本,所以能读到别人新提交的修改。互联网公司常有把默认改成 RC 的(间隙锁少、死锁率低),但 RR 是默认值且语义更稳——没有特殊理由别改。

回头看老王的三个怪象:对账脚本数字对不上,是代码里没把两次查询包进同一事务(或用了 RC 语义);报表出现幻影订单,是读了未提交数据(RU)或统计逻辑没对齐隔离级别;多算一笔则是范围统计撞上了并发 insert。按 RR + 明确事务边界重构后,全部消失。

MVCC 解决「读」,但两个事务同时改一行怎么办?这就是锁的地界:行锁、间隙锁、next-key lock,以及一场真实的死锁事故复盘——下一篇见。

咖啡凉了,记得趁热喝。

☕
503

10 年全栈工程师 · 503咖啡馆主理人

#MySQL#隔离级别#MVCC#ReadView#幻读

评论 (0)

热门推荐

连载中 11/22

主从搭建实操:从零配出一主两从

光讲原理不过瘾?手把手搭一主两从:my.cnf 六个参数、复制账号、GTID、CHANGE REPLICATION SOURCE TO、SHOW REPLICA STATUS 验收,附翻车排查清单。

#MySQL#主从复制#GTID#主从搭建#高可用
2026-05-07 · 10101 阅读 · 0 评论 · 0 赞
连载中 16/22

连接池:HikariCP 参数与连接风暴

连接池不是越大越好:8 核机器配 1000 连接反而更慢的数学原理,HikariCP 四个必调参数,maxLifetime 与 wait_timeout 的隐形陷阱。

#MySQL#连接池#HikariCP#maxLifetime#连接风暴
2026-05-10 · 9873 阅读 · 0 评论 · 0 赞
连载中 4/16

缓存穿透:恶意 ID 打穿 MySQL 的四道防线

请求的数据在缓存和数据库里都不存在时,缓存形同虚设。聊聊参数校验、空值缓存、布隆过滤器、限流熔断四道防线的原理与组合打法。

#Redis#缓存穿透#布隆过滤器#高可用
2026-05-16 · 9294 阅读 · 21 评论 · 287 赞