幻读是什么?
幻读可能产生数据一致性问题,数据一致性不仅指的是数据库内部数据状态,也包含日志逻辑和数据的一致性。下图就说明下这个问题:

可以看到上图中A会话的语义是把d=5修改为100其最终提交是在t6时刻,B会话的语义是在t2时刻把id=0的c、d修改为5,C会话的语义是在t4时刻加入一条数据(1,1,5),修改id=1的c为5。但是其在binlog中写的顺序是B和C先执行,A最后执行,就会导致所有d=5的值修改为100,这不符合我们想要的数据。如果我们把所有扫描到的数据都加上了锁,C会话中的插入的数据原先不存在,所以不会阻塞住。
在InnoDB中引入了间隙锁(Gap Lock),即锁住两个记录之间的间隙。间隙锁+行锁被称为范围锁(next-key Lock)。间隙锁可以解决幻读的问题,那会带来其他的问题么?答案是会的,间隙锁会带来死锁的,比如下图中的操作:

A会话中的查询会给(5,10)加间隙锁,由于查询语句不会冲突,所以B会话也会在(5,10)加上间隙锁。这时B会话执行插入操作会阻塞,需要等待A会话中锁释放。而A会话执行插入操作也会阻塞,需要等待B会话中锁释放,这样死锁就形成了。
加锁规则:
加锁时,锁的类型是范围锁。只会把扫描到的数据加锁
索引上的等值查询,是唯一索引的话,范围锁退化成行锁
索引上的等值查询,向右遍历时,且最后一个值不满足等值条件时,范围锁退化成间隙锁


在上图的A会话会锁住(10,15],(15,20)区间,结合加锁规则3,导致后面的B会话和C会话的操作阻塞。
文章转载自Lord Lean Notes,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




