文章目录
前言
系列文章
一、我是谁?
二、为什么有人会认为我是被MVCC干掉的
三、我真的是被MVCC解决的?
四、再聊当前读、快照读
当前读
快照读
五、告诉你们吧!当前读的情况下我是被next-key locks干掉的
六、幻读解决方案
七、扩展
事务ID是在何时分配的?
为什么事务ID差异特别大?
————————————————
一、我是谁?
先给大家做一个简单的自我介绍,我就是事务并发时会产生的三大问题之一。
我的其它俩兄弟脏读、不可重复读被MVCC在上一个回合无情的干掉了,至于上个回合发生了什么可以去看剧情回顾。
我的由来就是因为主人在操作一组数据时还有很多人也在对这组数据进行操作。
举一个简单的案例:
根据条件在对一组数据进行过滤返回的结果为100个,但是在主人操作的同时其他人又新增了符合条件的数据,然后主人再次进行查询时返回结果为101。第二次返回的数据跟第一次返回数据不一致。
于是我诞生了,大家还给我起了个很好听的名字幻读。
为什么会给我起这个名字呢!那是因为我给人们的现象好像出了幻觉一样。
二、为什么有人会认为我是被MVCC干掉的
为了演示方便,就直接使用之前的测试表来进行操作。
同时大家可以看到此表还有一些测试数据,一切从头开始,清空表。
清空表的命令truncate table_name
执行这个命令会使表的数据清空,并且自增ID会从1开始。
从执行过程来看,truncate table类似于drop table然后在create table,这里的环境都是测试环境,千万不要在线上进行操作,因为它绕过了DML方法,是不能回滚的。
进行了一点小插曲,进入正题。
根据上图的执行步骤,预期来说左边事务的第一条select语句查询结果为空。
第二个select查询结果为1条数据,包含右边事务提交的数据。
但在实际测试的情况下,第一次执行select和第二次执行select返回结果一致。
从这个案例中,可以得出结论确实在不可重复隔离级别下会解决幻读问题(在快照读的前提下)。
三、我真的是被MVCC解决的?
通过上述测试案例来看,貌似在MySQL中通过MVCC就解决我的引来的问题,那既然都解决了我的问题,为什么还有串行化的隔离级别呢!好疑惑啊!
带着这个疑问继续进行实验,为了方便就不再使用上边表结构了,建立一个简单的表结构。
再进入一个小插曲你知道在MySQL终端如何清屏吗?
执行命令system clear即可
接着开始新一轮的测试
上图案例事务1几次查询数据都是空。
此时事务2已经成功将数据插入并且提交。
但当事务1几次查询数据为空之后进行数据插入时,提示主键重复。
再来看一个案例
- step1:事务1开启事务
- step2:事务2开启事务
- step3:事务1查询数据只有一条数据
- step4:事务2添加一条数据
- step5:事务1查询数据为一条
- step6:事务2提交事务
- step7:事务1查询数据为一条
- step8:事务1修改name
- step9:猜想一下此时表内数据会发生什么改变
此案例中事务1始终读取数据都是一条数据,但是在修改数据时影响数据行数却是2,再次进行查看数据时竟然出现了事务2添加的数据。这也可以看作是一种幻读。
小结
通过以上俩个案例得知在MySQL可重复读隔离级别中并没有完全解决幻读问题,而只是解决了快照读下的幻读问题。
而对于当前读的操作依然存在幻读问题,也就是说MVCC对于幻读的解决是不彻底的。