Mysql —— 幻读
前言
在学习隔离级别以及mysql的并发问题处理时,一直对幻读的概念比较模糊,在网上搜集了很多资料,也是各有各的说法,后来找到一篇能拿出mysql官方文档的描述的文章,感觉比较靠谱,此处记录一下
幻读
The so-called phantom problem occurs within a transaction when the same query produces different sets of rows at different times. For example, if a SELECT is executed twice, but returns a row the second time that was not returned the first time, the row is a “phantom” row.
Mysql官方给出的幻读解释是:只要在一个事务中,第二次select多出了row就算幻读。
原文地址
文章的下方评论中给出了解释(可以直接 Ctrl + F “Mysql官方给出的幻读解释”)
https://github.com/Yhzhtk/note/issues/42
问题
虽然这位朋友给出了官方地址,但是他提到“如果这样理解的话,Mysql的RR级别确实防不住幻读”,并给出了实例:
a事务先select,b事务insert确实会加一个gap锁,但是如果b事务commit,这个gap锁就会释放(释放后a事务可以随意dml操作),a事务再select出来的结果在MVCC下还和第一次select一样,接着a事务不加条件地update,这个update会作用在所有行上(包括b事务新加的),a事务再次select就会出现b事务中的新行,并且这个新行已经被update修改了,实测在RR级别下确实如此。
此处先做记录,有待思考。
我更倾向于另外一种说法(可以直接 Ctrl + F “不能把快照读和当前读得到的结果不一样这种情况认为是幻读”):
在快照读读情况下,mysql通过mvcc来避免幻读。
在当前读读情况下,mysql通过next-key来避免幻读。
select * from t where a=1;属于快照读
select * from t where a=1 lock in share mode;属于当前读
不能把快照读和当前读得到的结果不一样这种情况认为是幻读,这是两种不同的使用。所以我认为mysql的rr级别是解决了幻读的。