间隙锁是什么就不解释了,产生间隙锁的场景 经我尝试发现了两种(1和3 也许还有其他情况,本人没试出来):
1、数据存在时:当a事务的update语句的where中使用的是普通索引(或者没用到索引)时,在a事务正常执行update之后 还没提交之前,b事务这时候执行insert语句会产生间隙锁。
2、如果where条件是主键索引的话,id=xxx这种非范围的条件,不会有间隙锁,如果是 id > xxx 、 id < xxx 这类范围的条件,b事务的update、insert满足条件也会产生被锁,但这种情况 应该是正常的写锁 不是间隙锁
3、当update语句的数据不存在时,会产生间隙锁
造成的影响就是 等待 阻塞,等待其他事物提交才能走流程。
1场景:
a事务
b事务:
可以看出a事务update之后 按照间隙锁的说法 会锁住v的值在6-16(不包含6、16)期间 所以第一条绿色的update语句执行成功没有等待。而执行第二条红色insert时 8 在6-16之间 所以发生了等待,要等待a事务提交才能执行,
这时我把sql kill掉 将v的值改为18 不在6-16之间,发现sql正常执行,没有阻塞,id=8的记录插入成功,所以换成了7, 将v的值重新改到6-16之间,重新执行,又产生阻塞,最后超时。
2场景:
数据还是场景1中的数据
红字为顺序
发现a事务中 执行id>=9的操作后,b事务的 insert 和 update 都收到影响 阻塞,然后超时回滚。如果a事务where条件是id=9,不会产生这种问题。
3场景:
数据还是场景1中的数据
红字为顺序
id为15和10的数据都是不存在的 update语句都能正常执行,但当执行sql3时 就发生了阻塞,应该是要等待2步骤的事务提交,这个场景应该就已经是间隙锁的情况了,
这时我又执行sql4,sql4直接报错提示了可能会产生死锁,然后同时,sql3执行成功了(应该是sql4直接回滚了)
间隙锁是为了干什么,还没搞清楚,搞清楚之后应该会更新。