【ⓂMySQL】MySQL InnoDB 解决幻读了吗?

能解决,但不能完全解决。

在RR和RC级别下,数据库的读分为快照读和当前读:

快照读:单纯的select操作。读取的是快照(ReadView)中的数据,可能是历史数据

当前读:select … for update/in share mode、update、insert、delete。读取的总是当前的最新数据

对于快照读,是通过mvcc来解决事务中的脏读、不可重复读以及幻读问题的。

实际上不管是RR还是RC,读取数据时根据undolog数据链的事务id和ReadView中各个参数(当前活跃的事务id集合,下一个未分配的事务id,活跃事务id中最小的事务id)对比的规则都是同一套,只是二者ReadView生成的时机不同。

对于RR隔离级别,ReadView是在事务读开始时候产生,在事务结束之前都是用这一个readView,因此无论怎么变化,看到的东西都不会变化。从而解决了脏读、不可重复读以及幻读问题。

对于RC隔离级别,每次读取的时候都会产生一个readView,因此无法解决不可重复读以及幻读问题。

因此:RR隔离级别下,快照读是可以解决脏读、不可重复读以及幻读问题的。

对于当前读,是通过锁(记录锁,间隙锁等)来解决脏读、不可重复读以及幻读问题的,你读取的行,以及行的间隙都会被加锁,直到事务提交时才会释放,其他的事务无法进行修改,所以也不会出现不可重复读、幻读的情形。而间隙锁在RR隔离级别中才生效。

因此:RR隔离级别下,当前读也是可以解决脏读、不可重复读以及幻读问题的。

那幻读是怎么产生的呢?为什么说RR隔离级别下没有完全解决幻读问题。

其实在RR级别下,有下面两种情况是可以产生幻读情况的:

1)事务1 先快照读,事务2新增了一条数据并提交事务,事务1再当前读。

2)事务1 先快照读,事务2新增了一条数据并提交事务,事务1对事务2提交的数据进行了修改,事务1再次快照读。

情况1不用说了吧,很好理解。对于情况2, 事务1的更新操作不属于快照读,因此事务1的更新操作是可以生效的,而当前数据会记录最新修改的记录,最新修改的记录为当前事务自己,所以是能看到的。

 

posted @ 2023-05-05 22:37  残城碎梦  阅读(75)  评论(0编辑  收藏  举报