阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

MySQL的REPEATABLE-READ隔离级别下读取到的“重复数据”

194次阅读
没有评论

共计 1622 个字符,预计需要花费 5 分钟才能阅读完成。

在 MySQL 中,使用 MVCC 来实现 REPEATABLE-READ 隔离级别,由于 SELECT 操作不会对数据加锁,其他回话可以修改当前回话所读取过的数据而不会被阻塞,因此读写不冲突。

在 MVCC 并发控制中,读操作可以分成两类:快照读 (snapshot read) 与当前读 (current read)。快照读,读取的是记录的可见版本 (有可能是历史版本),不用加锁。当前读,读取的是记录的最新版本,并且,当前读返回的记录,都会加上锁,保证其他事务不会再并发修改这条记录。

当事务中进行查询时,MySQL 会把快照读和当前读的结果进行合并再返回给客户端,而这个合并可能导致一些奇特的结果。

生成测试数据:

drop table tb002;
create table tb002(id int primary key,c2 int,unique index uni_c2(c2));
begin;
insert into tb002(id,c2) select 1,1;
insert into tb002(id,c2) select 2,2;
insert into tb002(id,c2) select 4,4;
commit;

假设有回话 A 和回话 B, 均使用 REPEATABLE-READ 隔离级别

##========================================================##

首先回话 A 执行 SQL:

begin;
select * from tb002;

返回结果如下:

MySQL 的 REPEATABLE-READ 隔离级别下读取到的“重复数据”

##========================================================##

然后回话 B 执行 SQL:

begin;
delete from tb002 where id=2;
commit;

由于回话 A 没有加锁,所以回话 B 能顺利完成删除并提交事务,当前数据库中无 C2= 2 的记录,且会话 B 提交事务释放锁。

##========================================================##

回到回话 A 执行 SQL:

insert into tb002(id,c2) select 3,2;

由于当前数据库中无 C2= 2 的记录,且其他回话没有在此 C2= 2 的范围上加锁,因此回话 A 可以完成 C2= 2 的数据插入。

在回话 A 上再次进行查询:

select * from tb002;

返回结果如:

MySQL 的 REPEATABLE-READ 隔离级别下读取到的“重复数据”

C2 上有唯一索引,但为什么查询结果中仍包含两条 C2= 2 的记录呢?ID= 2 的记录属于快照读的数据,ID= 3 的记录数据当前读的数据,MySQL 将当前读和快照读的数据进行简单的合并后返回给客户端,并不检查“结果数据是否满足唯一索引”的要求。

##========================================================##

上面的测试针对唯一索引进行,那如果针对主键会有啥区别呢?

将插入 SQL 修改为:

insert into tb002(id,c2) select 2,3;

即回话 B 删除的 ID 值和回话 A 新插入的 ID 值相同情况下,最后的查询结果并不会包含两条相同 ID 的记录,对于“快照读”和“当前读”两个结果集存在 ” 主键冲突“的情况,最终返回客户端的结果会”丢弃“快照读中的”老版本“记录,保留最新版本的记录。

可见对于主键不存在上述问题。

##========================================================##

总结:

在基于 MVCC 实现的 REPEATABLE-READ 隔离级别下,由于快照读和当前读的影响,会导致返回数据结果集超过”期望结果集“的情况,甚至返回结果集中包含重复的”唯一索引键“,但返回结果集中不会包含重复的“主键”(PS:单表查询的前提下)。

如果在事务中包含先插入后查询的情况,应该考虑上述问题对业务的影响。

本文永久更新链接地址 :http://www.linuxidc.com/Linux/2018-02/150769.htm

正文完
星哥玩云-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2022-01-22发表,共计1622字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中