橘子学MYSQL之幻读

一、幻读定义

这个的定义并不统一,SQL标准的定义非常简单,就是同一个事务进行的两次同样的查询,第2次查询得到了第1次查询中不存在的记录。
但是这个定义不太严谨,因为上面的描述着重在于描述,两次查询的结果不一致,那这就更加的贴近于不可重复读的定义了。所以我们看下大佬的解读。就是第一次查询的结果不能支持后面的业务了,我第一次查id=4的数据,没查到。此时我去插入这个数据,但是后续插入的时候告诉我这个数据存在了,这就是幻读。这里不做过多解释,这玩意越看越和可重复读一样。
但是我们可以结合关于幻读中的幻影行数据的定义来适当的理解一下这个东西。

一开始人们使用加锁的方式来解决遇到的各种一致性问题,对记录加锁时一个记录对应一个锁。但是很快人们发现如果在执行一个查询时,只能对那些查到的记录加锁,这样的话是不能阻止另外的事务新插入记录的;另一方面,如果执行的是DELETE语句,把记录删除了,也无法对记录加锁,这样别的事务可能插入新的记录来替代被删除的记录。
像这样新插入的记录,或被删除的记录都无法进行加锁,这样的记录也被称作phantom record,也就是幻影记录。
OK,我们之前看MVCC的时候,看到他是通过一致性视图的生成时机,结合版本链的读取规则来规避了各个隔离级别下面的隔离性问题。
但是很多地方都说在RR级别下,通过mvcc解决了普通读的幻读问题,通过加锁(next-key)解决了锁定读的幻读问题。其实还有一种情况的幻读没有被解决掉。下面我们来看下。

二、数据准备

CREATE TABLE `person` (
  `id` int(32) NOT NULL AUTO_INCREMENT COMMENT '主键,自增',
  `name` varchar(255) NOT NULL COMMENT '名字',
  `age` int(32) NOT NULL COMMENT '年龄',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 COMMENT='用户表';

-- ----------------------------
-- Records of person
-- ----------------------------
INSERT INTO `person` VALUES ('1', '梅西', '35');
INSERT INTO `person` VALUES ('2', '科比', '40');
INSERT INTO `person` VALUES ('3', '李哥', '28');

还是以前那张表,数据还是那三条。不过最近好像大巴黎要卖梅西,狗日的大巴黎。

三、问题复现

1、老套路,开两个dos窗口,两个事务开始并发操作,复现问题。两个事务隔离级别都是默认的RR级别,然后各自都能正常查询。查出来都是三条数据。
在这里插入图片描述
2、此时事务1开始启动,分别执行以下操作,
步骤1、查询数据,id =4的数据,此时数据并不存在自然查到的是空。

在这里插入图片描述
步骤2、此时事务2开启,插入一条数据,id为4
在这里插入图片描述
OK,此时事务2,插入一个数据id为4,但是并未提交,此时事务1是查不到的,而且你在事务1要修改这个数据因为隐式锁的存在也是阻塞的。此时我们提交事务2。
步骤3、提交事务2的插入操作。
在这里插入图片描述
此时数据库里面有了四个数据了,其中就包括id=4这个数据。但是你这时候在事务1里面还是读不到因为mvcc的存在。
步骤4、事务1中修改id=4的这个数据,
因为事务2的提交了,所以事务1此时再去修改,此时是Update操作为事务真正分配一个事务id,以前都是0,此时他的修改会分配一个事务id(此前最大事务id的递增加一),所以此时修改完了,会在版本链中加一个记录,此记录的trx_id就是这次这个分配的事务id,。
在这里插入图片描述
OK,此时我们在事务1中把岳飞改成了孟珙。
步骤5、事务1中此时再查询。
在这里插入图片描述
我们在事务1中查到了这个数据,也就是说出现了这种幻影行。

四、得出结论

结论就是RR隔离级别下还是会有幻影行数据的出现,也就是出现了幻读。我们不去纠结幻读的定义,我们通过明确的幻影行的定义出现,推出出现了幻读,这样就能纠结少一点,从而专注于问题。

五、分析原因

我们在上面事务1中做修改的时候,在版本链中加了一个版本,此时版本的trx_id是这个修改操作生成的新的事务id,因为事务2提交了,他不能阻止事务1做修改了。

别的就不看了,此时这个孟珙这个记录的事务id就是事务1的事务id,因为是事务1做的修改,此时我事务1再去读取这个id=4的记录,能读到也是合乎版本链的可见规则的。自己读自己就是第一条规则,所以是可见的。这就是出现上述问题的原因。所以RR解决了幻读,但是没有全部解决。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值