面试被反问,RR级别下能解决幻读问题那为什么不叫幻读级别?

字节后台一面凉经放这,有需要自己去看哈 字节跳动飞书后台工程师一面,应该是个凉经

Q:你讲讲innodb的锁机制吧
A:blablablabla介绍了行锁表锁意向锁,读锁写锁
Q:还有呢
A:介绍了四种锁算法,record lock, gap lock, next-key lock, previous-key lock,最后我提了一嘴,innodb在rr隔离级别下是通过next-key算法来避免幻读问题的(先别骂,第一次面试紧张死了,确实有问题)
Q:在rr级别下能解决幻读问题那为什么不叫幻读级别呢,你做过实验吗?
A:我跟着书里做过实验,开了两个事务blablablabla

反正最后凉了就是了,感谢信也无,冷处理(安详.jpg
然后重新翻书看,然后和牛友们探讨,然后和学长询问,仍旧觉得没问题,只是觉得应该加上mvcc来描述会更好

《MySQL技术内幕 InnoDB存储引擎》
面试被反问,RR级别下能解决幻读问题那为什么不叫幻读级别?
MySQL8.0官方文档面试被反问,RR级别下能解决幻读问题那为什么不叫幻读级别?

并且自己也重新做了实验
有以下数据
面试被反问,RR级别下能解决幻读问题那为什么不叫幻读级别?
现在我们开启两个事务A,B,事务A执行select,事务B执行insert,分快照读和当前读两种情况。

快照读

顾名思义,读的是快照,具体实现是mvcc,再详细是undo log,不做细究。
面试被反问,RR级别下能解决幻读问题那为什么不叫幻读级别?

当前读

当前读是通过上锁实现的,也就是innodb通过next-key算法(行锁+间隙锁)为我们将这块区域锁上了,所以事务B无法对其修改。

面试被反问,RR级别下能解决幻读问题那为什么不叫幻读级别?

然后和朋友研究,最终发现,就描述上来说,next-key算法确实能避免幻读现象,这句话本身没问题,但是面试官的问题应该是rr隔离级别下怎么能避免幻读问题?

确实如书中所说,next-key能解决幻读问题,但这是手动加的,而在可序列化的隔离级别下则是默认实现的。
其次你说那mvcc的快照读呢,不也能避免吗?

起先,我确实一直是这么理解的,直到朋友给我看了这篇博客: 史上最详尽,一文讲透 MVCC 实现原理

然后我进行了如下实验,也就是那篇博客的6.3的例子
还是原汁原味的表
面试被反问,RR级别下能解决幻读问题那为什么不叫幻读级别?
事务A除了select还执行update,事务B负责插入数据,于是。
面试被反问,RR级别下能解决幻读问题那为什么不叫幻读级别?

幻读现象发生了!

由这个例子说明,一旦事务A的修改操作覆盖到了其他事务插入的“幻行”,那么在下次select的时候,也会把这行数据一起查出来。具体实现这里不谈,与undo log有关,那篇博客都详细说了。

这个问题MySQL官方文档中也提出了,引用了其他博主的翻译,没原链接
面试被反问,RR级别下能解决幻读问题那为什么不叫幻读级别?

最后,假如面试官再次问我 —— RR级别下能解决幻读问题那为什么不叫幻读级别?
A:平常我们学习的rr确实存在幻读问题,但是在innodb下不同,它可以解决,但是解决的并不完美。
首先我们可以通过手动加锁阻塞另一个线程的insert,也就是通过innodb的next-key算法,其次我们也可以通过mvcc实现快照读,但是mvcc存在缺陷,就是一旦某个事物在事务中的修改操作覆盖到了其他事务插入的“幻行”,那么这些“幻行”在下次查询时就会再次出现,从而出现幻象问题。