MySQL REPEATABLE READ真的不会出现幻读么
MySQL REPEATABLE READ真的不会出现幻读么
众所周知,MySQL在事务隔离级别REPEATABLE READ
的情况下,是可以防止幻读现象的产生的,这点不同于SQL标准。但是,MySQL真的就做的很完美么?让我们来看一个例子,我们会发现MySQL
在REPEATABLE READ
的隔离级别下,竟然也出现了幻读现象。依旧以mysqld 8.0.20-debug
为例子。
1 表
表的schema为:
drop table t;
create table t(
a int PRIMARY KEY,
b int
);
insert into t values(1,1),(2,2),(4,4),(5,5);
2 例子
两个session的操作顺序如下:
时间线 | session A | session B |
---|---|---|
1 | SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; begin; select * from t; |
|
2 | SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; begin; insert into t values(3,3); |
|
3 | select * from t; | |
4 | commit; | |
5 | select * from t; /*发生了更新,导致下面的select语句看到了session b提交的结果*/ update t set b = b * 10; select * from t; |
在sessionA中,当我们执行update t set b = b * 10;
之后,在执行select * from t
查询语句,得到的结果如下:
+---+------+
| a | b |
+---+------+
| 1 | 10 |
| 2 | 20 |
| 3 | 30 |
| 4 | 40 |
| 5 | 50 |
+---+------+
可以看到,a = 3这一行的数据也查询到了,其实和直观猜测的一样,是因为update语句的原因,才导致session A看到了session B提交的结果,即便是REPEATABLE READ
隔离级别下也会出现这样的结果。这个是什么原因呢?其实这个问题早就有人提出来了,并且也给出了答案,详情见淘宝的官方博客,这片文章里有详细的介绍,其实并不是一个bug。