MYSQL分析案例

假设数据库隔离级别为 RR,事务 A 先执行普通SELECT * FROM user WHERE id < 5(快照读),此时事务 B 插入 id=3 的行并提交,事务 A 再次执行相同的普通 SELECT,能看到 id=3 的行吗?为什么?

完整解析

结论:事务 A看不到 id=3 的行。
核心原因(结合 RR 级别 ReadView 规则):
  1. RR 级别 ReadView 的生成规则 :事务 A 第一次执行普通 SELECT(快照读)时,会生成一个固定的 ReadView ,这个 ReadView 包含了 "生成瞬间的活跃事务 ID 列表、min_trx_id、max_trx_id" 等关键信息,且在事务 A 提交前不会更新、不会重建
  2. 数据可见性判断
    • 事务 B 是在事务 A 生成 ReadView 之后开启并提交的,因此事务 B 的事务 ID ≥ ReadView 的max_trx_id(高水位线);
    • 根据 ReadView 的可见性规则:数据行的修改事务 ID ≥ max_trx_id时,该数据对当前事务不可见
    • 即使事务 B 提交了 id=3 的行,事务 A 的快照读仍会复用最初的 ReadView,因此无法看到这个新插入的行。

再来分析第二种情况(在第一问的情况下)

若事务 A 后续执行UPDATE user SET name = 'test' WHERE id < 5(当前读),能修改到事务 B 插入的 id=3 的行吗?这个过程中会触发什么锁机制?

1. 为什么能修改到 id=3 的行?(当前读 vs 快照读的本质区别)
  • 快照读(普通 SELECT)依赖 ReadView 读取历史版本,而当前读(UPDATE/DELETE/SELECT ... FOR UPDATE)不依赖 ReadView,会直接读取数据的最新版本;
  • 事务 B 已经提交了 id=3 的行,该行是数据库中的 "最新数据",因此事务 A 执行 UPDATE(当前读)时,会扫描到这个最新的 id=3 的行,并执行修改操作;
  • 这也是 RR 级别下 "极特殊幻读场景" 的体现:快照读看不到,但当前读能修改到,看似 "矛盾",实则是两种读取方式的机制不同。
2. 触发的锁机制(Next-Key Lock):

事务 A 执行UPDATE user SET name = 'test' WHERE id < 5时,InnoDB 会先执行 "当前读扫描",再加锁,过程如下:

  1. 第一步:扫描最新数据:遍历 id < 5 的所有行(包括事务 B 插入的 id=3 的行);
  2. 第二步:加记录锁 :给 id=3 的行加记录锁,防止其他事务同时修改 / 删除这行;
  3. 第三步:加间隙锁 :给 id <5 的间隙(如 (0,3)、(3,5))加间隙锁,防止其他事务在这个范围内插入新行;
  4. 最终触发的是Next-Key Lock(记录锁 + 间隙锁),而非单独的间隙锁或记录锁。
相关推荐
祈禾7 小时前
Redis三大缓存问题与分布式锁
运维·数据库·redis·笔记·分布式·缓存
DBA小马哥7 小时前
关系型数据库核心概念手册:SQL、事务与存储引擎的技术脉络
数据库·sql
丫头,冲鸭!!!7 小时前
记账网站3-连数据库
数据库·个人开发
灯澜忆梦8 小时前
【MySQL12】进阶篇 | SQL优化
数据库·sql·mysql·性能优化
IvorySQL8 小时前
PostgreSQL 日报|PG18.5 回归测试崩溃问题(8 月 12 日)
大数据·数据库·人工智能·postgresql
ltl8 小时前
学习型查询优化器:Neo、Bao、Balsa 与 LLM-CBO
数据库
ltl8 小时前
持久内存退场之后:ZNS SSD 与下一代非易失内存
数据库
故乡dee云11 小时前
AWS 产品太多不会选?按“网站、数据库、文件、日志”4 类需求快速匹配
数据库·云计算·aws
曹牧12 小时前
C#:问号
前端·数据库·c#
奇树谦13 小时前
《现代 Key-Value 数据库原理:从 B+Tree 到 LSM Tree》-第五篇:现代数据库横向对比
数据库·lsm-tree