问题:
现象:事务A明明查出来没有数据ID为3的数据,但是插入的时候却报了主键冲突的问题,出现幻读的场景
事务A在更新name为cc的数据之前明明查出来只有一条匹配的,但是更新结果却对两条数据产生了影响,出现了幻读的场景。
如果只看上面的两种场景的话其实我们可以下结论说MySQL在RR级别下没有解决幻读的问题,但是网上关于幻读的讨论一大堆,而且官方也没有给出一个明确的定性,到底是什么原因呢?这时候就要引出MySQL的当前读与快照读
在RR级别下,通过MVCC机制,可以让数据变得可重复读,而MVCC实现原理就是在开启事务后的第一次select操作的同时创建一份快照,接下来再执行select操作就是从快照中读取的。
注意:
- 第一次select的时候才会创建快照,你可以测试在开启事务A之后,先不执行select操作,这时候让事务B插入一条数据,接着事务A再执行select的话会查出来事务B插入的数据。
- 快照读针对的是select操作,从上面可以看到我们在事务A的最后一步select的话读取到的是快照中的数据,但是update,delete,insert读取到的却不是
快照读虽然解决了可重复读,但是他可能让读出来的数据不是最新的数据,而是历史数据
MySQL对于update、insert、delete使用的都是当前读的模式,再执行这几个操作的时候读取到的都是当前最新的数据。别的事务提交的数据也可以查到,甚至别的数据未提交的数据也可以查到,你可以测试下在事务A插入一个id为10的数据但是不提交,这时候如果事务B同样插入一个数据为10的数据的话就会阻塞,你可以认为加了一个排他锁,你也可以站在另外一个角度认为他查询到了其他的事务操作的数据。
再了解了上面的问题以后我们再来看看为什么有的人认为MySQL在RR级别下解决了幻读,有的认为没有解决。
我认为这是对幻读的定位、认知不同。
在认为解决的人看来。幻读不能把快照读和当前读混起来操作,这是两种使用方式。幻读应该是在快照读或当前读本身的场景下,两次读取结果一致,而MySQL在快照读的情况下通过MVCC已经解决了,在当前读的情况MySQL通过next-key来解决了。
在认为没有解决的人看来。幻读应该不关心快照读还是当前读,只要第二次读(这个读比较广泛)读出了第一次读没有的数据就叫幻读,在这种定义下,我们可以从上面的两种场景看出,MySQL没有解决。
原文:https://www.cnblogs.com/colin-xun/p/13746292.html