间隙锁和死锁

间隙锁产生的条件

  • 使用 > 、 < 、between 等区间条件
  • delete 不存在的数据

间隙锁的例子

当我们通过一个参数去删除一条记录的时候,如果参数在数据库中存在,那么这个时候产生的是普通行锁,锁住这个记录,然后删除,然后释放锁。如果这条记录不存在,问题就来了,数据库会扫描索引,发现这个记录不存在,这个时候的 delete 语句获取到的就是一个间隙锁,然后数据库会向左扫描扫到第一个比给定参数小的值,向右扫描扫描到第一个比给定参数大的值,然后以此为界,构建一个区间,锁住整个区间内的数据。

总结

两个事务即使生成的间隙锁 (next-key 锁) 的范围是一样的,也不会发生冲突,因为间隙锁目的是为了防止其他事务插入数据,因此间隙锁与间隙锁之间是相互兼容的。

在执行插入语句时,如果插入的记录在其他事务持有间隙锁范围内,插入语句就会被阻塞,因为插入语句在碰到间隙锁时,会生成一个插入意向锁,然后插入意向锁和间隙锁之间是互斥的关系。

如果两个事务分别向对方持有的间隙锁范围内插入一条记录,而插入操作为了获取到插入意向锁,都在等待对方事务的间隙锁释放,于是就造成了循环等待,满足了死锁的四个条件:互斥、占有且等待、不可强占用、循环等待,因此发生了死锁。

参考连接

https://cloud.tencent.com/developer/article/1806998

https://www.xiaolincoding.com/mysql/lock/show_lock.html