MySQL的锁(二)
幻读现象
幻读指的是一个事务在前后两次查询同一个范围的时候,后一次查询看到了前一次查询没有看到的行。 (仅在“当前读”的情况下才会出现)
幻读会带来什么问题?
1.语义上,破坏了锁声明,明明锁住?为什么可以修改我锁住的所有满足条件行,
2.数据一致性
如何解决幻读? 锁上所有扫描到的行?事实证明这样也未能解决,因为存在着新插入的记录,因为锁的时候,这条记录还没有。
产生幻读的原因事,行锁只能锁住行,但是新插入记录这个动作,要更新的事记录之间的“间隙”。因此为了解决幻读问题,InnoDB只好引入新的锁,也就是Gap Lock
间隙锁,顾名思义,锁的就是两个值之间的空隙,select * from t where d = 5 for update的时候,就不止是给数据库中已有的6个记录加上了行锁,还同时加了7个间隙锁
在一行行的扫描中,不仅给行加上了行锁,还给行两边的空隙,加上了间隙锁。间隙锁和行锁不一样,行锁分为读锁和写锁。和行锁有冲突关系的是另一个行锁。而对于间隙锁,跟间隙锁存在冲突关系的,是往这个间隙中插入一个记录这个操作,
间隙锁之间互不冲突,他们有相同的目标,就是保护这个间隙,不允许插入值。
间隙锁和行锁合称为 next-key lock 每个 next-key lock 是开闭区间 ,
间隙锁和 next-key lock 的引入,帮我们解决了幻读的问题,但同时也带来了一些“困扰”
间隙锁的引入,可能会导致同样的语句锁住更大的范围,这其实是影响了并发度。
间隙锁是在可重复读隔离级别下才会生效的。所以,你如果把隔离级别设置为读提交的话,就没有间隙锁了。但同时,你要解决可能出现的数据和日志不一致问题,需要把 binlog 格式设置为 row 。