https://www.yduba.com/biancheng-5811592809.html
Read Committed隔离级别,在这种隔别级别下,可能会出现不可重复读

Repeatable Read [ri’pi:təbl](可重复读)MySQL的默认事务隔离级别
它确保在同一事务中多次读取同样的记录结果是一样的。当事务a开启的时候,事务b对a查找的内容进行修改,b提交事务之后,事务a执行相同select得到的还是刚进入事务时候查到的内容(只限于不加锁的select读,也就是快照读)。

可重复读隔离级别可能会出现:幻读 (Phantom Read)。简单的说,幻读指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影” 行
例如:第一个事务查询一个 User 表 id=100 发现不存在该数据行,这时第二个事务又进来了,新增了一条 id=100 的数据行并且提交了事务。
这时第一个事务新增一条 id=100 的数据行会报主键冲突,第一个事务再 select 一下,发现 id=100 数据行已经存在,这就是幻读。

例子

现在我们来举个例子说明一下 幻读,如:在test库里有一个表 tx, 表里有3条数据,测试之前先把自动提交事务关闭,并把隔离级别设置成Repeatable Read,如下图:

  1. set autocommit = 0;
  2. set session TRANSACTION ISOLATION LEVEL Repeatable read;
  3. select @@tx_isolation;


3可重复读 Repeatable Read - 图1
这时,客户端B也开启了一个事务,(客户端B也要先设置好当前会话的隔离级别和关闭自动提交事务,要和客户端A保持一致),并更新了一条数据,并提交事务,如下图
3可重复读 Repeatable Read - 图2
特别注意:此时的客户A还没有提交事务,这时,客户A来查询数据会还是不变,如:
3可重复读 Repeatable Read - 图3
这种情况下,就不会像上一节,我们学的Read Committed(读取提交内容)级别下的,同一事务,不同时刻读到的数据不一致。我们再做一次插入数据,如下图:
3可重复读 Repeatable Read - 图4
客户端还是原来的数据。当客户端A提交事务后,就会得到新的数据。

由以上的实验可以得出结论,可重复读隔离级别只允许读取已提交记录,
像以上 的实验,就没有出现数据幻读的问题。如果事务a再次查询的结果,包含事务b修改之后,或者事务b新增的记录,那就是出现了幻影记录。
innodb通过mvcc的一致性视图,解决了不加锁的select(快照读)的可重复读问题。但可能出现幻读问题,因为select的时候没有加锁,其它事务就有可能修改select的结果,导致select后续的操作幻读了。这个时候可以通过给select加锁的方式强制事务排序(加锁之后会存在记录锁和间隙锁,数据间隙部分也会锁住),避免出现幻读。
MVCC和事务隔离级别的关系