15.幻读是什么?幻读有什么问题2022-03-02

一、幻读是什么?

在MySQL的隔离级别RR下,幻读是指读到了新增的数据。

1.幻读问题一:只给某一行加锁

for update就会给该条sql加上行锁,但是一定就不会有问题了吗?


问题一

统一放一起就是这样的

update t set d=5 where id=0; /*(0,0,5)*/
update t set c=5 where id=0; /*(0,5,5)*/

insert into t values(1,1,5); /*(1,1,5)*/
update t set c=5 where id=1; /*(1,5,5)*/

update t set d=100 where d=5;/*所有d=5的行,d改成100*/

原因:“select * from t where d=5 for update 这条语句只给 d=5 这一行,也就是 id=5 的这一行加锁”导致的。

2.幻读问题二:新增的加不了锁
问题二

可以看到,按照日志顺序执行,id=0 这一行的最终结果也是 (0,5,5)。所以,id=0 这一行的问题解决了。但同时你也可以看到,id=1 这一行,在数据库里面的结果是 (1,5,5),而根据 binlog 的执行结果是 (1,5,100),也就是说幻读的问题还是没有解决。为什么我们已经这么“凶残”地,把所有的记录都上了锁,还是阻止不了 id=1 这一行的插入和更新呢?原因很简单。在 T3 时刻,我们给所有行加锁的时候,id=1 这一行还不存在,不存在也就加不上锁。
也就是说,即使把所有的记录都加上锁,还是阻止不了新插入的记录

二、怎么解决幻读?

用间隙锁(Gap lock)+行锁
间隙锁和行锁合称 next-key lock,是一个左开右闭区间。
例如:0,5,6三行分别是 (-∞,0]、(0,5]、(5,6]、(6, +supremum]。
间隙锁之间的兼容关系是怎样的?
在同时插入不存在的行时,关系如下

image.png

三、next-key lock一定是安全的吗?

不一定,因为如果同时对一个间隙进行插入操作的时候可能会出现死锁,间隙锁只存在可重复读的隔离级别下。

四、读提交+把binlog的格式改成row

binlog_format=row

1.这样会有问题吗?
2.在备份期间,备份线程用的是可重复读,而业务线程用的是读提交。同时存在两种事务隔离级别,会不会有问题?
3.这两个不同的隔离级别现象有什么不一样的,关于我们的业务,“用读提交就够了”这个结论是怎么得到的?

五、思考题

思考题

如果你之前没有了解过本篇文章的相关内容,一定觉得这三个语句简直是风马牛不相及。但实际上,这里 session B 和 session C 的 insert 语句都会进入锁等待状态。你可以试着分析一下,出现这种情况的原因是什么?

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容