记一次接口压测时导致的mysql死锁问题。
1:死锁发生后,查看日志。mysql:版本5.6.26,
事务隔离级别:READ-COMMITTED
表结构:
使用命令查看锁信息:SHOW ENGINE INNODB STATUS; 信息如下: ===================================== 2022-07-01 15:08:12 0x7fec9e2fc700 INNODB MONITOR OUTPUT ===================================== 省略。。。。 *** (1) TRANSACTION: 这是一个事务:记为事务1 TRANSACTION 460053728, ACTIVE 9 sec starting index read mysql tables in use 1, locked 1 LOCK WAIT 14 lock struct(s), heap size 1136, 2 row lock(s) MySQL thread id 6051936, OS thread handle 140654036281088, query id 436999648 172.17.52.15 pri_u_user updating //下面这是 事务1 执行的SQL语句 UPDATE t_primary_subscribe_tender SET Finvestor_scb_bond_id=174437 WHERe (Finvestor_scb_bond_id IS NULL AND Fseller_scb_bond_id = 174440 AND Finvestor_org_id = 'e38757fb4fed4571981dd612d6394590' AND Finvestor_tenant_id = 136) *** (1) WAITING FOR THIS LOCK TO BE GRANTED: //等待这个锁 被授权 RECORD LOCKS space id 8394 page no 8385 n bits 120 index PRIMARY of table `db_primary_market`.`t_primary_subscribe_tender` trx id 460053728 lock_mode X locks rec but not gap waiting //事务1想对 空间为8394,索引页8385,偏移量为120的 主键索引加入X锁,非间隙锁 //下面是这条数据的 具体的值,上面锁的是主键,所以会有表的字段完整数据信息,字段太多省略了,只留有用的。 // 0:代表第一个字段,len 8:代表长度,hex:代表16进制,000000000006ecec:具体值(取8位,len的长度,从右往左数)。 翻译下来:id=453868(hex:0006ecec) Record lock, heap no 48 PHYSICAL RECORD: n_fields 36; compact format; info bits 0 0: len 8; hex 000000000006ecec; asc ;; id = 453868 1: len 6; hex 00001b6bdb68; asc k h;; 省略。。。。, //所以翻译下来,事务1:想要主键id=453868的索引。 *** (2) TRANSACTION: 这是另一个事务:记为事务2 TRANSACTION 460054031, ACTIVE 6 sec starting index read mysql tables in use 1, locked 1 15 lock struct(s), heap size 1136, 11 row lock(s) MySQL thread id 6052043, OS thread handle 140701521143552, query id 437013921 172.17.52.15 pri_u_user updating UPDATE db_primary_market.t_primary_subscribe_tender SET Finvestor_scb_bond_id=174437 WHERe (Finvestor_scb_bond_id IS NULL AND Fseller_scb_bond_id = 174440 AND Finvestor_org_id = 'e38757fb4fed4571981dd612d6394590' AND Finvestor_tenant_id = 136); *** (2) HOLDS THE LOCK(S): //事务2持有的锁。 RECORD LOCKS space id 8394 page no 8385 n bits 120 index PRIMARY of table `db_primary_market`.`t_primary_subscribe_tender` trx id 460054031 lock_mode X locks rec but not gap Record lock, heap no 48 PHYSICAL RECORD: n_fields 36; compact format; info bits 0 0: len 8; hex 000000000006ecec; asc ;; id= 453868 //这是表的第一个字段,是16进制的,len 8:取8位,0006ecec转成10进制是453868 省略。。。。。 //翻译下来,事务2:持有id= 453868 的锁,用X锁锁住的。这里很关键,要在代码中 找出是在哪一步持有这个锁的, //我这边查日志 分析出来,有一条 插入语句,insert(),因为主键是自增的,所以 自增的这条数据是id=453868。 *** (2) WAITING FOR THIS LOCK TO BE GRANTED://事务2:等待锁被授权 //这里是等待 idx_seller_scb_bond_id 索引(Fseller_scb_bond_id= 174440,Fid=453868这条数据) 加入X锁(非间隙锁), RECORD LOCKS space id 8394 page no 11103 n bits 488 index idx_seller_scb_bond_id of table `db_primary_market`.`t_primary_subscribe_tender` trx id 460054031 lock_mode X locks rec but not gap waiting Record lock, heap no 195 PHYSICAL RECORD: n_fields 2; compact format; info bits 0 //这里是 索引 Fseller_scb_bond_id的信息 0: len 8; hex 800000000002a968; asc h;; Fseller_scb_bond_id = 174440 1: len 8; hex 000000000006ecec; asc ;; Fid = 453868 *** WE ROLL BACK TRANSACTION (1) //这里是回滚的相关日志,省略了。篇幅太长 ---------------------------- END OF INNODB MONITOR OUTPUT ============================
根据以上日志 分许出来:执行顺序是这样的。
执行结果为:
分析原因:



