当前位置: 首页 > news >正文

MYSQL RR 解决“脏读+不可重复读“和“幻读“的本质区别

RR 解决脏读 + 不可重复读 和 RR 解决幻读:MVCC 解决快照读。这两个是否矛盾

一、先说结论:完全不矛盾

问题解决机制解决哪类读
脏读 + 不可重复读MVCC(ReadView 复用)单行读
幻读MVCC(快照读)范围读
幻读(当前读)Next-Key Lock范围读 + 锁

关键洞察

  • MVCC 一个机制,既解决了不可重复读,又解决了快照读的幻读
  • 两种场景都是"读快照"RR 下 ReadView 复用 → 看不到其他事务的新数据
  • 不可重复读和幻读本质相同:都是"读不到其他事务新数据"——单行级别就是不可重复读,范围级别就是幻读

二、3 大问题本质

不可重复读:单行被修改
-- 老哥的报表例子 BEGIN; SELECT balance FROM account WHERE id = 1; -- 第 1 次读,balance=1000 -- 其他事务:UPDATE account SET balance = 900 WHERE id = 1; COMMIT; SELECT balance FROM account WHERE id = 1; -- 第 2 次读,balance=900 -- ⚠️ 同一事务,同一行,结果不同 → 不可重复读
幻读:范围被插入
-- 老哥的批量报表例子 BEGIN; SELECT * FROM account WHERE balance > 1000; -- 第 1 次查,5 条 -- 其他事务:INSERT INTO account (balance) VALUES (2000); COMMIT; SELECT * FROM account WHERE balance > 1000; -- 第 2 次查,6 条 -- ⚠️ 同一事务,同一范围,行数不同 → 幻读

本质对比

维度不可重复读幻读
关注点单行被修改范围被插入/删除
结果变化变了行数变了
底层机制都是 MVCC ReadView 复用都是 MVCC ReadView 复用
区别同一行的不同版本范围中多了/少了行

**所以——MVCC 解决不可重复读,自然就解决了快照读的幻读。因为它们都是"看不到新数据"。

三、MVCC 一个机制,两个效果

RR 隔离级别下: - 事务开始第一次 SELECT 时创建 ReadView - 整个事务期间复用这个 ReadView - 看不到 ReadView 之后才提交的数据 ↓ 看不到"被修改的数据"(不可重复读解决) ↓ 看不到"被插入的数据"(幻读解决)

一句话总结

"MVCC 看不到 ReadView 之后的新数据,自然就既解决不可重复读(修改)又解决幻读(插入)。一个机制,两个效果。"

四、为什么会有"矛盾"的感觉?

感觉矛盾,可能是因为4 大隔离级别的标准定义

隔离级别解决没解决
RU脏读 / 不可重复读 / 幻读
RC脏读不可重复读 / 幻读
RR(标准)脏读 /不可重复读幻读
SE全部

标准 SQL 定义里 RR 是不解决幻读的!但MySQL InnoDB 通过 MVCC + Next-Key Lock 突破了标准定义,几乎解决了幻读

所以老哥看到的两个说法

1."RR 解决脏读 + 不可重复读"(标准 SQL 定义)

2."RR 解决幻读"(MySQL InnoDB 实际实现)

它们都对!只是描述的角度不同

  • 角度 1:按标准 SQL 定义,RR 不解决幻读
  • 角度 2:按 MySQL InnoDB 实现,RR通过 MVCC + Next-Key Lock 几乎解决幻读

五、RR 解决幻读的 2 大机制MVCC 解决快照读 + Next-Key Lock 解决当前读

机制 1:MVCC 解决快照读的幻读普通 SELECT
-- RR 隔离级别 + 普通 SELECT BEGIN; -- 创建 ReadView,假设 m_ids=[2,3,4,5], min=2, max=6 SELECT * FROM account WHERE balance > 1000; -- 看到 5 条 -- 期间事务 6 INSERT 并提交一条 -- 事务 6 的 trx_id=6 > max=6,不在 ReadView 范围内 SELECT * FROM account WHERE balance > 1000; -- 仍看到 5 条(ReadView 复用) COMMIT;

关键ReadView 看不到 trx_id > max_trx_id 的事务提交的数据,所以新插入的行看不到幻读解决

机制 2:Next-Key Lock 解决当前读的幻读SELECT FOR UPDATE
-- RR 隔离级别 + 当前读 BEGIN; SELECT * FROM account WHERE balance > 1000 FOR UPDATE; -- 加 Next-Key Lock -- 锁定范围:balance > 1000 涉及的索引区间 -- 期间其他事务尝试 INSERT balance > 1000 INSERT INTO account (balance) VALUES (2000); -- ⚠️ 阻塞! SELECT * FROM account WHERE balance > 1000; -- 仍看到 5 条 COMMIT;

关键Next-Key Lock = 记录锁 + 间隙锁锁定了"可能插入的位置"防止新数据插入

六、面试话术

"不矛盾

'RR 解决脏读 + 不可重复读'标准 SQL 定义——按 SQL 标准 RR 不解决幻读。

'RR 解决幻读'MySQL InnoDB 实际实现——InnoDB 用MVCC 解决快照读幻读(ReadView 复用),用Next-Key Lock 解决当前读幻读(记录锁+间隙锁)。

核心洞察不可重复读和幻读本质相同——都是看不到其他事务的新数据单行级别叫不可重复读,范围级别叫幻读。MVCC 一个机制同时解决。"

七、项目实战对照

RR 默认
@Transactional // RR public void generateReport(Report report) { // 1. 单行查(不可重复读解决) Report existing = reportMapper.selectById(report.getId()); // 整个事务期间,existing 不会被其他事务的修改影响 // 2. 范围查(幻读解决) List<Report> pending = reportMapper.selectByStatus("pending"); // 整个事务期间,pending 不会被其他事务的插入影响 // 3. 当前读(Next-Key Lock 解决幻读) List<Report> all = reportMapper.selectByStatusForUpdate("pending"); // 加锁,其他事务不能 INSERT status='pending' 的报表 }
RC 查询
@Transactional(isolation = Isolation.READ_COMMITTED) // RC public List<MaskedData> queryLatestMasked() { // 1. 单行查(能重复读 → 老数据)— mpvs 不在意 // 2. 范围查(能幻读 → 新数据)— mpvs 在意,要看最新 return dataMaskMapper.selectAll(); // 看到最新 }

用 RR不可重复读 + 幻读都不能有(同一报表要一致)。

用 RC能看到最新(有些任务要看最新数据)。"

八、记忆口诀

"不可重复读和幻读,本质都是看不到新数据"

"单行级别 = 不可重复读,范围级别 = 幻读"

"MVCC 一个机制,同时解决两个"

"标准 SQL RR 不解决幻读,MySQL InnoDB 解决了"

"快照读靠 MVCC,当前读靠 Next-Key Lock"

http://www.jsqmd.com/news/1003881/

相关文章:

  • 如何免费实现7种音频格式高效转换:FlicFlac专业解决方案指南
  • 2026南通全媒体运营TOP榜单:短视频策划拍摄/账号运营/话题打造/达人联动/信息流投放/微信公众号及视频号内容运营与活动策划一站式优选 - 品牌发掘
  • 2026年 厦门连接线/端子线/电子线/排线/跳线/USB连接线/插头线厂家推荐:精准传输与耐用工艺之选 - 品牌发掘
  • 2026年 江西凉亭厂家推荐榜单:六角/八角/双层/四角凉亭,古韵匠心与户外园林精品之选 - 品牌发掘
  • Linux inode_permission inode权限检查与acl处理
  • 别再找旧脚本了!MMdetection 3.X 版本官方工具一键生成PR曲线图(附完整配置流程)
  • 2026年C语言找工作难吗?普通人还能找到好工作吗?
  • 兰州黄金回收实测 余生珍宝六店行情解析 - 余生黄金回收
  • C盘存储爆红,哪些文件类型可以安全删除?一张清单分三档
  • CVI工程中直接调用自定义DLL的实操资源包(含双项目源码与一键构建脚本)
  • Python生产级API设计:可观测、可演进、可防御的请求生命周期治理
  • TMS320F28335四层小板:6×8cm带USB供电、JTAG下载、复位键和全引脚标注
  • 六盘水珍宝黄金回收测评 2026买金避坑指南 - 余生黄金回收
  • 浙江大学LaTeX论文模板:5分钟快速生成专业毕业论文的终极指南
  • 避开回收套路荆州六大黄金门店测评 - 余生黄金回收
  • 2026年英文降AIGC率指南:别盲目同义词替换!5种降AI高效方法实测(附工具测评) - 降AI实验室
  • C盘大文件怎么搬到D盘或其他分区?从定位到迁移的完整操作
  • 别再只会录宏了!WPS JS宏实战:用filter和箭头函数5分钟搞定数据清洗
  • Spring Boot 文件上传大小限制配置全解析
  • 从英国到葡萄牙,这群欧洲青年为何把目光投向中国开源?
  • 寄行李大件什么物流最省钱?用“寄半折”比价立省一半 - 快递物流资讯
  • 2026甘孜州权威认证贵金属回收 TOP5+黄金回收白银回收铂金回收门店地址电话推荐
  • Logisim 2.7.1 手把手:从零搭建一个支持13种运算的32位MIPS ALU(附完整电路图)
  • 2026年北京企业法律顾问怎么挑?5个核心关键点防踩雷 - 本地品牌推荐
  • STM32CubeMX配置I2C驱动AT24C64 EEPROM,手把手教你搞定用户设置数据存储(附完整工程代码)
  • 2026年q2正规青年旅行社官网品牌技术维度解析:美国旅游/318川藏线自驾游/中国青年旅行社官网/优选推荐 - 优质品牌商家
  • 2026年新中式门楼设计施工服务商评测:五大品牌对比 - 优质品牌商家
  • 保姆级教程:用ADB命令备份与删除长安UNI-V车机自带软件(附完整命令清单)
  • Windows电脑频繁弹广告怎么彻底清除?从定位来源到卸载残留的完整方法
  • 从“滋滋”声到清晰通话:一个移动端音频工程师的AEC避坑实战录