MySQL间隙锁原理深度详解
|
| 1 | begin; |
|
| 2 | select * from test where id>1; | begin; |
| 3 |
| insert into test values(21,3); |
| 4 |
| commit; |
| 5 | select * from test where id>1 for update; |
|
| 6 | commit; |
|
有兴趣的同学可以按照这个步骤操作一下看下效果,针对上面的操作来做一下分析:
事务A在第2步使用的是快照读,此时生成了Read View查询出来的数据是id>1这个区间的所有数据;
事务B在第3步插入了一条id为21的数据,因为事务A没有对数据加锁,所以事务B可以正常插入;
第5步事务A查询时查出了事务B插入的数据,因此产生幻读;
# 3.4.1 原因分析
第5步的时候使用了for update,即使用的是当前读,不会再读取Read View,而读取的是当前最新的数据,所以读出了事务B插入的数据。
# 3.4.2 总结
结合上面的分析结果,做最后如下小结
MySQL默认隔离级别可重复读很大程度上解决了幻读问题,在快照读情况下是通过MVCC解决,在第一次执行查询时生成一张Read View,后续每次快照读都是读这张Read View;
在当前读情况下是加锁来解决,枷锁会阻塞其他事务的当前读,从而避免幻读;
然而可重复读并不能完全解决幻读,比如当一个事务里面使用快照读之后又使用当前读的话就还是可能会出现幻读。
上次更新: 2024/11/01, 16:22:32