幻读Java_关于幻读 - hellopretty - 博客园

不可重复读

在同一事务中,两次读取同一数据,得到内容不同,侧重点在于数据修改

幻读

同一事务中,用同样的操作读取两次,得到的记录数不相同,幻读的侧重点在于两次读取的纪录数量不一致

不可重复读和幻读在概念上有些交叉,对于不可重复读来说,在同一个事务中,如果读取到的记录数量发生变化,也可以看作是一种不可重复读,同样,对于幻读来说,同一个事务中的读取结果数量一致,但是内容发生了变化,也可以看成是一种不可重复读。

对于mysql,这里讨论一下read committed和repeatable read两个事务隔离级别的不可重复读和幻读:

read committed:

在read committed隔离级别下,存在不可重复读和幻读现象。

起两个事务1和2,1采用快照读读取数据,2修改其中一条满足1查询条件的数据并提交,这时1再快照读一次,就会发现2添加的记录,这就是不可重复读。但如果1采用当前读方式读取数据,由于读取数据的时候会给满足条件的数据加锁,因此,事务2无法修改数据内容,如果单纯从数据内容发生变化这个方面来考虑的话,是不会出现不可重复读的问题的。同时,如果考虑到记录数量增减,由于read committed隔离级别并没有gap锁,所以虽然不能修改采用当前读方式锁定的数据,但是可以在查询条件满足的范围内增加新的数据,这也可以看作是一种不可重复读,但显然这种情况划分到幻读更好。

repeatable read:

在repeatable read隔离级别下,mysql不仅解决了不可重复读,还通过gap锁的引入,解决了幻读的问题。

具体分析与上边类似,只是在repeatable隔离级别下,如果事务2对某些数据作了更新,事务1通过快照读已经不会读取到数据变化,所以repeatable read隔离级别解决了不可重复读的问题。同时由于引入了gap锁,事务2也无法在事务1采用当前读的前提下在事务1的查询条件满足范围内插入新的数据,所以记录数量不会发生变化,也就不存在幻读问题。

当隔离级别是可重复读,且禁用innodb_locks_unsafe_for_binlog的情况下,才可以利用gap锁避免幻读,gap锁是为了保证语句级别binlog的串行化。

总结:

如果仅仅考虑数据内容发生变化来衡量不可重复读,那么只有在read committed隔离级别的快照读中才会出现不可重复读,如果考虑数据数量变化,那么在read committed隔离级别的快照读和当前读中都存在不可重复读现象;

read committed隔离级别下,快照读和当前读都会产生幻读现象;

repeatable read隔离级别下,只有快照读会产生幻读现象,当前读已经通过gap锁的引入消除了幻读现象。

(何登成大神在博客中将幻读的定义限制在当前读的前提下,个人认为还是幻读和可重复读的具体定义不清晰)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值