【为什么mvcc只解决了部分幻读】

MVCC与幻读问题的深入解析

简单来说,MVCC(多版本并发控制)就像给数据库拍“快照”。它让事务在读取数据时,看到的是自己开始时的那个“瞬间画面”,而不会受其他事务新增或修改数据的影响。但为什么说它只解决了“部分”幻读呢?我们分三步理解:


1. 什么是幻读?

假设你开了一个事务,要做两件事:

  1. 第一次查询:查“工资大于5000的员工”,返回10条记录。
  2. 第二次查询:同样的查询,结果却变成11条了!因为另一个事务在你两次查询之间,偷偷插入了一条新员工数据。

这种“凭空多出来”的现象就是幻读。它破坏了你事务内多次查询结果的一致性。


2. MVCC如何“部分”解决幻读?

  • 核心机制:MVCC在事务开始时拍一张“快照”(Read View),之后所有读操作都基于这个快照。
  • 效果
    • 其他事务新增的数据(比如那条新插入的员工),在你的快照里根本不存在。
    • 所以无论你查多少次,看到的都是同一份数据,避免了幻读。

看起来解决了?但有个漏洞!


3. 为什么只是“部分”解决?

问题出在:事务内如果有更新操作(比如UPDATE、DELETE),会导致“快照”失效!

举个🌰:

  1. 你第一次查“工资>5000的员工”,返回10条。
  2. 另一个事务插入了一条工资6000的新员工(id=100),并提交。
  3. 你执行了一条更新操作:UPDATE 员工 SET 工资=7000 WHERE 工资>5000
    • 这时MySQL会悄悄升级为“当前读”(Latest Read),直接看最新的数据,而不是快照。
    • 于是这条更新操作会影响到新插入的id=100的员工!
  4. 你再次查询“工资>5000的员工”,会发现id=100这条记录也被更新了,虽然它原本不在你的快照里。

结果:你明明没查到这条数据,但更新时却影响到了它,之后查询又能看到它——这就是MVCC没解决的幻读!


总结

  • MVCC防住了“只读不写”的幻读:如果事务内只有查询操作,快照机制能完全避免幻读。
  • 但防不住“边读边写”的幻读:一旦事务内有更新操作,MySQL会切换到最新数据,导致新插入的数据被“意外”修改,从而出现幻读。

彻底解决幻读:需要MVCC+间隙锁(Gap Lock)。间隙锁会锁住数据之间的“空隙”,阻止其他事务插入新数据,堵住这个漏洞。所以严格来说,InnoDB在RR级别下,是通过MVCC+间隙锁共同解决幻读的。MVCC单枪匹马只能算“部分解决”

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值