幻读(phantom read)详解

基本定义(也是来自网络)

当某个事务a范围查询数据时,另一个事务b在该范围内插入了数据,当事务a再次范围查询时,会产生幻行(即多了事务b插入的那行数据)。

网络上的其他定义

看看幻读的正确理解

时间点

事务A

事务B

1

开启事务

2

开启事务

3

查询数据“张三”,不存在

4

插入数据“张三”

5

提交事务

6

查询数据“张三”,不存在

7

插入数据“张三”,不成功

事务A查询“张三”,查询不到,插入又不成功,“张三”这条数据就像幻觉一样出现。这就是所谓的“幻读”。网上对“幻读”还是其他的解释,都是错误的。比如像“幻读”和“不可重复读”是一样,只不过“幻读”是针对数据的个数。这些理解都是错误的。

参考链接:MySQL中的幻读,你真的理解吗? - 云+社区 - 腾讯云

详解

先说结论:【基本定义】的理解是对的,【网络上的其他定义】是不准确的。

1. 幻读是repeatble read隔离级别下的产物,但并不是repeatble read隔离级别应该有的现象。按照隔离级别的定义,重复读一定是相同的结果。

2. 那为啥会产生幻读呢?是mysql等数据库一开始在范围查询时,没有加范围锁。其他事务b可以在事务a的处理过程中在范围内插入新纪录。(数据库未能完全实现repeatble read隔离,导致了幻读现象)

3. 解决幻读的措施:众所周知的mvcc机制。

4. 解决幻读的另一个措施:next-key锁(范围加锁)。

参考链接:MySQL :: MySQL 8.0 Reference Manual :: 15.7.4 Phantom Rows

 为啥会出现网络上的其他定义

mysql的 mvcc实现,会隐含的给数据表加上两个版本控制列。

它的insert操作,插入数据的同时,会写入版本号。

它的update操作,其实是插入了一条新的数据,同时更新了新老数据的版本号。

所以会导致以下情况:

1. 事务a查询数据1(空)-》事务b插入数据1-》事务a查询数据1(空)-》事务a插入数据1(失败)。这非常正常!已经有数据1了,凭什么事务a要插入成功?它并不是幻读

2.  事务a查询数据1(空)-》事务b插入数据1-》事务a查询数据1(空)-》事务a更新数据1(成功)-》事务a查询数据1(有数据)。这也很正常,因为update其实是一个insert操作,它的版本号已经更新了,为啥不能读到。它也不是幻读。

总的来说,那些错误的定义,描述的是mysql解决幻读后出现的现象,并不是幻读本身。查找了很多博客,发现幻读真的是众说纷纭,最后找到的是mysql官网的解释,加上mysql的mvcc版本号机制,推测了部分错误定义的来源,也不一定对,仅供参考。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
脏读(Dirty Read)是指一个事务读取到了另一个事务未提交的数据。在并发环境下,一个事务读取到了另一个事务尚未提交的数据,如果这个尚未提交的数据最终被回滚,则读取到的数据就是无效的。脏读可能会导致不一致的数据状态。 不可重复读(Non-repeatable Read)是指在同一事务中,多次读取同一数据,但得到的结果不一致。这是因为在这个过程中,其他事务可能已经修改了该数据。不可重复读可能会导致事务处理逻辑错误。 幻读Phantom Read)是指在同一事务中,多次查询同一个范围的数据,但得到的结果集不一致。这是因为在这个过程中,其他事务可能已经新增或删除了符合该范围条件的数据行。幻读可能会导致数据查询结果不准确。 这些问题都是由于并发事务操作数据库时引起的,为了解决这些问题,数据库提供了不同的隔离级别(如READ COMMITTED、REPEATABLE READ、SERIALIZABLE)来控制事务之间的隔离程度。 - 脏读可以通过使用READ COMMITTED隔离级别来避免。在READ COMMITTED隔离级别下,一个事务只能读取到已经提交的数据。 - 不可重复读可以通过使用REPEATABLE READ隔离级别来避免。在REPEATABLE READ隔离级别下,事务读取的数据是一致的,即使其他事务对该数据进行了修改。 - 幻读可以通过使用SERIALIZABLE隔离级别来避免。在SERIALIZABLE隔离级别下,事务读取的结果集是一致的,即使其他事务对该范围内的数据进行了新增或删除操作。 需要根据具体的业务场景和需求选择适当的隔离级别来避免脏读、不可重复读和幻读问题,并且注意隔离级别的选择会影响到数据库的性能和并发性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值