【转载】死锁日志解读
下面是日志内容:
1 | ------------------------ |
下面分成:(1)TRANSACTION、(1)WAITING FOR THIS LOCK TO BE GRANTED、(2)TRANSACTION、(2)HOLDS THE LOCK(S)、(2)WAITING FOR THIS LOCK TO BE GRANTED、WE ROLL BACK TRANSACTION (1)
1代表事务1,2代表事务2
- **(1)TRANSACTION: #事务1 **
TRANSACTION 462308399, ACTIVE 33 sec starting index read
事务编号为 462308399 ,活跃33秒,starting index read 表示事务状态为根据索引读取数据。
常见的其他状态:
- fetching rows 表示事务状态在row_search_for_mysql中被设置,表示正在查找记录。
- updating or deleting 表示事务已经真正进入了Update/delete的函数逻辑(row_update_for_mysql)
- thread declared inside InnoDB 说明事务已经进入innodb层。通常而言 不在innodb层的事务大部分是会被回滚的。
mysql tables in use 1, 说明当前的事务使用一个表,locked 1 表示表上有一个表锁,对于DML语句为LOCK_IX
LOCK WAIT 2 lock struct(s), heap size 360, 1 row lock(s)
LOCK WAIT表示正在等待锁, 2 lock struct(s) 表示trx->trx_locks锁链表的长度为2,每个链表节点代表该事务持有的一个锁结构,包括表锁,记录锁以及auto_inc锁等。本案例中2locks 表示IX锁和lock_mode X(Next-key lock)
heap size 360 表示事务分配的锁堆内存大小,一般没有什么具体的用处。
1 row lock(s)表示当前事务持有的行记录锁/gap 锁的个数。
delete from ty where a=5 表示事务1在执行的sql
- ** (1)WAITING FOR THIS LOCK TO BE GRANTED**
RECORD LOCKS space id 219 page no 4 n bits 72 index idxa
of table test
.ty
trx id 462308399 lock_mode X waiting
RECORD LOCKS 表示记录锁,space id为219,page号4 ,n bits 72表示这个聚集索引记录锁结构上留有72个Bit位
表示事务1 正在等待表 ty 上的 idxa 的 X 锁本案例中其实是Next-Key lock
事务2的log 和上面分析类似
- ** (2)TRANSACTION、HOLDS THE LOCK(S) **
** RECORD LOCKS space id 219 page no 4 n bits 72 index idxa
of table test
.ty
trx id 462308398 lock_mode X **
显示了事务2 insert into ty(a,b) values(2,10)持有了a=5 的Lock mode X |LOCK_GAP ,不过我们从日志里面看不到 事务2 执行的 delete from ty where a=5;这点也是造成DBA 仅仅根据日志难以分析死锁的问题的根本原因。
- ** (2)WAITING FOR THIS LOCK TO BE GRANTED**
** RECORD LOCKS space id 219 page no 4 n bits 72 index idxa
of table test
.ty
trx id 462308398 lock_mode X locks gap before rec insert intention waiting **
表示事务2的insert 语句正在等待插入意向锁 lock_mode X locks gap before rec insert intention waiting (LOCK_X + LOCK_REC_GAP )
这里需要各位注意的是锁组合,类似lock_mode X waiting ,lock_mode X,lock_mode X locks gap before rec insert intention waiting 是我们分析死锁的核心重点。
锁组合
锁组合呢?
首先我们要知道对于MySQL有两种常规锁模式
- LOCK_S(读锁,共享锁)
- LOCK_X(写锁,排它锁)
最容易理解的锁模式,读加共享锁,写加排它锁。
锁属性
- LOCK_REC_NOT_GAP (锁记录)
- LOCK_GAP (锁记录前的GAP)
- LOCK_ORDINARY (同时锁记录+记录前的GAP 。传说中的Next Key锁)
- LOCK_INSERT_INTENTION (插入意向锁,其实是特殊的GAP锁)
锁的属性可以与锁模式任意组合。例如:
lock->type_mode 可以是Lock_X 或者Lock_S
locks gap before rec 表示为gap锁:lock->type_mode & LOCK_GAP
locks rec but not gap 表示为记录锁,非gap锁:lock->type_mode & LOCK_REC_NOT_GAP
insert intention 表示为插入意向锁:lock->type_mode & LOCK_INSERT_INTENTION
waiting 表示锁等待:lock->type_mode & LOCK_WAIT