MySQL中的死锁
2025/6/15大约 3 分钟
MySQL中的死锁
Next-Key Lock
Innodb为了解决可重复读隔离级别下的幻读问题,引入了Next-Key Lock,它包括了记录锁(Record Lock)和间隙锁(Gap Lock)。
- 记录锁:锁的记录本身。
- 间隙锁:锁的是两个值之间的间隙,防止其它事物在这个间隙里插入新的数据,从而避免幻读。间隙锁之间不互斥,也就是说两个事务可以同时持有包含共同间隙的间隙锁。但如果是插入两个相同的next-key lock,因为包含了记录锁,是会被阻塞的。
共同的间隙锁包含:
- 两个完全相同的间隙锁
- 一个间隙锁的区间是另一个间隙锁区间的子集。
需要注意的是,如果update语句的where的条件没有用到索引,就会全表扫描,在一行行扫描时,不仅会对记录加上记录锁,还会给记录两边的空隙加上间隙锁,相当于锁住整一个表,由于MySQL是两阶段锁,所有锁在事务结束后才会释放。
插入意向锁
执行Insert语句插入时,会先判断待插入记录的下一条记录上是否已经被加了间隙锁,如果已加间隙锁,会生存插入意向锁并且设为等待状态,而插入意向锁和间隙锁是互斥的,所以对于select for ... update
,然后insert into ...
这样的语句,即使select
和insert
的ID(或者索引项)不一样,但获取的间隙锁区间是共同的,则有可能在并发场景下死锁。