The so-called phantom problem occurs within a transaction when the same query produces different sets of rows at different times. For example, if a SELECT is executed twice, but returns a row the second time that was not returned the first time, the row is a “phantom” row.

这里讲的最好

1. 查看事务隔离级别(mysql8)  
show variables like '%transaction_isolation%';

2. 修改隔离级别
set global transaction isolation level read uncommitted;
set global transaction isolation level read committed;
set global transaction isolation level repeatable read;
show variables like '%transaction_isolation%';

3. 进行事务操作
SET AUTOCOMMIT=0 ;
select * from account where id>2;
begin ;
update account set balance=1 where id=1;
commit;
insert into account (name,balance) values('zs',100);

总结 RU:A事务能看到B事务未提交的更改 RC:A事务能看不到B事务未提交的更改,但能看到B事务提交的更改,存在幻读(select count(*)会增加),不可重复读(select * from a where id=1 会变化)。 RR:A事务看不到B事务提交的更改,A修改B修改过的数据,会被阻塞,解决了不可重复读,依然存在幻读。
证据:

  1. A事务,B事务开启,B事务新增id=1,A事务无法查询到,但如果A事务insert id=1,则报错
  2. A事务,B事务开启,B事务新增id=1,A事务update所有数据,则A会match update的数据比正常情况下多一条

但是,当隔离级别是可重复读,且禁用innodb_locks_unsafe_for_binlog的情况下,在搜索和扫描index的时候使用的next-key locks可以避免幻读。

innodb_engine RR级别 具有行级锁和间隙锁,保证范围查询是所有存在与不存在的行数据都被锁上
for update是当前读,锁住索引记录之间的范围,避免插入记录。
因为普通读是不会加锁的读,故不会有next-key locks的使用,解决幻读的手段是MVCC