InnoDB中的 REPEATABLE READ 这种隔离级别通过间隙锁+MVCC解决了大部分的幻读问题,但是并不是所有的幻读都能解读,想要彻底解决幻读,需要使用Serializable的隔离级别。
RR中:
通过间隙锁解决了部分当前读的幻读问题,
通过增加间隙锁将记录之间的间隙锁住,避免新的数据插入。
RR中,通过MVCC机制的,解决了快照读的幻读问题,RR中的快照读只有第一次会进行数据查询,后面都是直接读取快照,所以不会发生幻读。
① 但是,如果两个事务,事务1先进行快照读,然后事务2插入了一条记录并提交,再在事务1中进行update新插入的这条记录是可以更新成功的,再次查询,会查询到事物 2 插入的数据, 这就是发生了幻读。
② 还有一种场景,如果两个事务,事务1先进行快照读,然后事务2插入了一条记录并提交,在事务1中进行了当前读之后,再进行快照读也会发生幻读。
注意:如果事务 1 的 select 是 select for update 则不再是快照读,是当前读,当前读的话就会出现脏读,没有 for update 则是 快照读,是不会出现幻读的
即:SELECT 是快照读,无法真正“避免”幻读,只是不可见。UPDATE 是当前读,有可能造成幻读。
有这样一张表:
create table student
(
id int auto_increment
primary key,
name varchar(255) null,
age int null
);
create index name_index
on student (name);
INSERT INTO test.student (id, name, age) VALUES (4, null, null);
INSERT INTO test.student (id, name, age) VALUES (3, '', 1);
INSERT INTO test.student (id, name, age) VALUES (2, null, 2);
INSERT INTO test.student (id, name, age) VALUES (1, '', 1);
初始化数据是这样的
演示 MVCC 当前读的幻读问题
前提:RR 级别
评论区