Mysql可重复隔离级别完全解决幻读问题了吗?

58 阅读2分钟

Mysql可重复隔离级别完全解决幻读问题了吗?

何为幻读?

当同一个查询在不同的时间产生不同的结果集时,事务中就会出现所谓的幻象问题。(前后两个相同的范围查询查询的记录数不同就可能产生了幻读)

==结论:可重复隔离级别不能完全解决幻读问题==

快照读是如何避免幻读的?

在可重复隔离级别下,快照读通过MVCC(多版本并发控制)来避免幻读

实现方式是开始事务后,执行第一条select查询语句后会创建一个read view快照版本,通过这个Read View 就可以在undo log版本链中找到事务开始时的数据,所以在事务过程中每次查询数据都是事务最开始时的数据,即使中途有其他事务修改数据库的数据,对该事务也是不可见的,所以很好的避免了幻读

当前读是如何避免幻读的?

在可重复隔离级别下,当前读主要是通过==next-key lock(记录锁+间隙锁)==方式解决了幻读,当执行当前读的select语句时就会加上next-key lock,这个时候,如果中途有其他事务想要修改这个范围的数据,或在这个范围添加新的数据,都会被阻塞,无法操作成功,所以就很好的避免了幻读问题

可重复隔离级别下的幻读问题

场景一

事务A修改了提交事务的事务B插入的数据,,这个时候这条新数据记录的事务trx_id(事务id)就变成了事务A的事务id,之后事务A再去查询就会能查询到这条记录,于是就发生了幻读

这个场景很少发生,但是确实也存在,因为事务A都第一次都没查询到这条数据,为什么还要去修改这条数据:sweat_smile:

image-20240425203021170

场景二

事务A第一次查询执行的是快照读语句,默认不会加间隙锁,此时事务B插入一条数据,事务A再执行当前读语句,导致幻读

image-20240425203454754

要避免这个场景的幻读的问题的话,可以再事务一开始的时候就执行当前读,对对应范围的数据加上间隙锁