Mysql死锁如何排查?insert on duplicate死锁排查过程分析( 二 )


文章插图
 
从日志我们可以看到事务1正在执行的SQL为:
insert into song_rank(songId,weight) values(18,100) on duplicate key update weight=weight+1该条语句正在等待索引songId_idx的插入意向排他锁:
lock_mode X locks gap before rec insert intention waiting(2)事务2日志分析

Mysql死锁如何排查?insert on duplicate死锁排查过程分析

文章插图
 
从日志我们可以看到事务2正在执行的SQL为:
insert into song_rank(songId,weight) values(16,100) on duplicate key update weight=weight+1该语句持有一个索引songId_idx的间隙锁:
lock_mode X locks gap before rec该条语句正在等待索引songId_idx的插入意向排他锁:
lock_mode X locks gap before rec insert intention waiting(3)锁相关概念补充(附)
考虑到有些读者可能对上面insert intention锁等不太熟悉,所以这里这里补一小节锁相关概念 。官方文档
InnoDB 锁类型思维导图:
Mysql死锁如何排查?insert on duplicate死锁排查过程分析

文章插图
 
我们主要介绍一下兼容性以及锁模式类型的锁
① 共享锁与排他锁:
InnoDB 实现了标准的行级锁,包括两种:共享锁(简称 s 锁)、排它锁(简称 x 锁) 。
  • 共享锁(S锁):允许持锁事务读取一行 。
  • 排他锁(X锁):允许持锁事务更新或者删除一行 。
如果事务 T1 持有行 r 的 s 锁,那么另一个事务 T2 请求 r 的锁时,会做如下处理:
  • T2 请求 s 锁立即被允许,结果 T1 T2 都持有 r 行的 s 锁
  • T2 请求 x 锁不能被立即允许
如果 T1 持有 r 的 x 锁,那么 T2 请求 r 的 x、s 锁都不能被立即允许,T2 必须等待T1释放 x 锁才可以,因为X锁与任何的锁都不兼容 。
② 意向锁
  • 意向共享锁( IS 锁):事务想要获得一张表中某几行的共享锁
  • 意向排他锁( IX 锁): 事务想要获得一张表中某几行的排他锁
比如:事务1在表1上加了S锁后,事务2想要更改某行记录,需要添加IX锁,由于不兼容,所以需要等待S锁释放;如果事务1在表1上加了IS锁,事务2添加的IX锁与IS锁兼容,就可以操作,这就实现了更细粒度的加锁 。
InnoDB存储引擎中锁的兼容性如下表:
Mysql死锁如何排查?insert on duplicate死锁排查过程分析

文章插图
 
③ 记录锁(Record Locks)
  • 记录锁是最简单的行锁,仅仅锁住一行 。如:SELECT c1 FROM t WHERE c1 = 10 FOR UPDATE
  • 记录锁永远都是加在索引上的,即使一个表没有索引,InnoDB也会隐式的创建一个索引,并使用这个索引实施记录锁 。
  • 会阻塞其他事务对其插入、更新、删除
记录锁的事务数据(关键词:lock_mode X locks rec but not gap),记录如下:
RECORD LOCKS space id 58 page no 3 n bits 72 index `PRIMARY` of table `test`.`t` trx id 10078 lock_mode X locks rec but not gapRecord lock, heap no 2 PHYSICAL RECORD: n_fields 3; compact format; info bits 0 0: len 4; hex 8000000a; asc ;; 1: len 6; hex 00000000274f; asc 'O;; 2: len 7; hex b60000019d0110; asc ;;④ 间隙锁(Gap Locks)
  • 间隙锁是一种加在两个索引之间的锁,或者加在第一个索引之前,或最后一个索引之后的间隙 。
  • 使用间隙锁锁住的是一个区间,而不仅仅是这个区间中的每一条数据 。
  • 间隙锁只阻止其他事务插入到间隙中,他们不阻止其他事务在同一个间隙上获得间隙锁,所以 gap x lock 和 gap s lock 有相同的作用 。
⑤ Next-Key Locks
  • Next-key锁是记录锁和间隙锁的组合,它指的是加在某条记录以及这条记录前面间隙上的锁 。
⑥ 插入意向锁(Insert Intention)
  • 插入意向锁是在插入一行记录操作之前设置的一种间隙锁,这个锁释放了一种插入方式的信号,亦即多个事务在相同的索引间隙插入时如果不是插入间隙中相同的位置就不需要互相等待 。
  • 假设有索引值4、7,几个不同的事务准备插入5、6,每个锁都在获得插入行的独占锁之前用插入意向锁各自锁住了4、7之间的间隙,但是不阻塞对方因为插入行不冲突 。
事务数据类似于下面:
RECORD LOCKS space id 31 page no 3 n bits 72 index `PRIMARY` of table `test`.`child`trx id 8731 lock_mode X locks gap before rec insert intention waitingRecord lock, heap no 3 PHYSICAL RECORD: n_fields 3; compact format; info bits 0 0: len 4; hex 80000066; asc f;; 1: len 6; hex 000000002215; asc " ;; 2: len 7; hex 9000000172011c; asc r ;;...(4)SQL加锁分析


推荐阅读