幻读
- 在可重复读隔离级别下,普通的查询是快照读,是不会看到别的事务插入的数据的。因
此,幻读在“当前读”下才会出现。 - 幻读仅专指“新插入的行”。
产生的问题
- 语义不同
- 数据库一致性被破坏
如何解决
因为行锁只能锁住行,但是无法阻止新插入。
所以InnoDB引入新的锁,间隙锁
间隙锁
行间隙锁住不让插入,间隙为key不存在的范围值,但是有最大值
如果key是0,5
那么间隙锁就是(-∞,0)、(0,5)、(5,+supremum]
InnoDB 给每个索引加了一个不存在的最大值supremum
间隙锁导致的问题
select * from t where id=N for update;
/* 如果行不存在 */
insert into t values(N,N,N);
/* 如果行存在 */
update t set d=N set id=N;
commit;
一旦并发,间隙锁之间不会冲突,所以会导致死锁。InnoDB 的死锁检测马上就发现了这对死锁关系,让 session 的 insert 语句报错返回了。