幻读
首先我们要搞明白何谓幻读,目前网上的众多解释幻读的博文个人感觉仔细设想一下就能找出推翻的例子,就像博文把 非阻塞IO 等同为 异步IO,然后好多文章都纷纷借用,其实这俩货是完全不同,非阻塞IO 是 同步IO 中的一种模式,并非 异步IO。错误的观点都被大众认同的 "正确化" 了,扯远了,回归主题。
幻读会在 RU / RC / RR 级别下出现,SERIALIZABLE 则杜绝了幻读,但 RU / RC 下还会存在脏读,不可重复读,故我们就以 RR 级别来研究幻读,排除其他干扰。
注意:RR 级别下存在幻读的可能,但也是可以使用对记录手动加 X锁 的方法消除幻读。SERIALIZABLE 正是对所有事务都加 X锁 才杜绝了幻读,但很多场景下我们的业务sql并不会存在幻读的风险。SERIALIZABLE 的一刀切虽然事务绝对安全,但性能会有很多不必要的损失。故可以在 RR 下根据业务需求决定是否加锁,存在幻读风险我们加锁,不存在就不加锁,事务安全与性能兼备,这也是 RR 作为mysql默认隔是个事务离级别的原因,所以需要正确的理解幻读。
幻读错误的理解:说幻读是 事务A 执行两次 select 操作得到不同的数据集,即 select 1 得到 10 条记录,select 2 得到 11 条记录。这其实并不是幻读,这是不可重复读的一种,只会在 R-U R-C 级别下出现,而在 mysql 默认的 RR 隔离级别是不会出现的。
这里给出我对幻读的比较白话的理解:
幻读,并不是说两次读取获取的结果集不同,幻读侧重的方面是某一次的 select 操作得到的结果所表征的数据状态无法支撑后续的业务操作。更为具体一些:select 某记录是否存在,不存在,准备插入此记录,但执行 insert 时发现此记录已存在,无法插入,此时就发生了幻读。
网友评论