记一次线上死锁问题排查

一、分析死锁日志

  1. 去数据库中将死锁日志下载

执行sql: SHOW ENGINE INNODB STATUS

=====================================
2023-11-23 21:01:25 0x7f75724c3700 INNODB MONITOR OUTPUT
=====================================
Per second averages calculated from the last 4 seconds
-----------------
BACKGROUND THREAD
-----------------
srv_master_thread loops: 57152137 srv_active, 0 srv_shutdown, 4929829 srv_idle
srv_master_thread log flush and writes: 62081753
----------
SEMAPHORES
----------
OS WAIT ARRAY INFO: reservation count 104206559
OS WAIT ARRAY INFO: signal count 8669932669
RW-shared spins 0, rounds 2364586667, OS waits 27018476
RW-excl spins 0, rounds 6610507666, OS waits 18381943
RW-sx spins 27801716, rounds 434452192, OS waits 5336373
Spin rounds per wait: 2364586667.00 RW-shared, 6610507666.00 RW-excl, 15.63 RW-sx
------------------------
LATEST DETECTED DEADLOCK
------------------------
2023-11-07 18:57:11 0x7f6767121700
*** (1) TRANSACTION:
TRANSACTION 2831641219, ACTIVE 0 sec inserting
mysql tables in use 1, locked 1
LOCK WAIT 5 lock struct(s), heap size 1136, 3 row lock(s), undo log entries 2
MySQL thread id 19046815, OS thread handle 140079181850368, query id 11788450197 10.2.0.21 jdadmin update
INSERT INTO md_file_info  ( object_type,
object_type2,
object_id,
file_url,
create_id,
create_by,
create_time,
update_id,
update_by,
update_time )  VALUES  ( 40,
10,
525293,
'/minio/cert/30/18220118906/4e8679a0df9740a41f7a931f9b3638b0.jpg',
119954,
'张健',
'2023-11-07 18:57:11.802',
119954,
'张健',
'2023-11-07 18:57:11.802' )
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 322 page no 82099 n bits 512 index index_md_file_info_object of table `smolp`.`md_file_info` trx id 2831641219 lock_mode X locks gap before rec insert intention waiting
Record lock, heap no 443 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
 0: len 8; hex 80000000000803ed; asc         ;;
 1: len 4; hex 80000028; asc    (;;
 2: len 4; hex 80000014; asc     ;;
 3: len 8; hex 80000000008cab40; asc        @;;

*** (2) TRANSACTION:
TRANSACTION 2831641218, ACTIVE 0 sec inserting
mysql tables in use 1, locked 1
80 lock struct(s), heap size 24784, 123 row lock(s), undo log entries 74
MySQL thread id 19049437, OS thread handle 140082087597824, query id 11788450284 10.2.0.22 jdadmin update
INSERT INTO md_file_info  ( object_type,
object_type2,
object_id,
file_url,
create_id,
create_by,
create_time,
update_id,
update_by,
update_time )  VALUES  ( 40,
50,
525292,
'/minio/cert/30/18391186518/2a2d63100c81201660371f4e7a57ef48.jpg',
89894,
'姬存浪',
'2023-11-07 18:57:11.863',
89894,
'姬存浪',
'2023-11-07 18:57:11.863' )
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 322 page no 82099 n bits 512 index index_md_file_info_object of table `smolp`.`md_file_info` trx id 2831641218 lock_mode X locks gap before rec
Record lock, heap no 443 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
 0: len 8; hex 80000000000803ed; asc         ;;
 1: len 4; hex 80000028; asc    (;;
 2: len 4; hex 80000014; asc     ;;
 3: len 8; hex 80000000008cab40; asc        @;;

*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 322 page no 82099 n bits 512 index index_md_file_info_object of table `smolp`.`md_file_info` trx id 2831641218 lock_mode X locks gap before rec insert intention waiting
Record lock, heap no 443 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
 0: len 8; hex 80000000000803ed; asc         ;;
 1: len 4; hex 80000028; asc    (;;
 2: len 4; hex 80000014; asc     ;;
 3: len 8; hex 80000000008cab40; asc        @;;

*** WE ROLL BACK TRANSACTION (1)
------------
TRANSACTIONS
------------
Trx id counter 2921447495
Purge done for trx's n:o < 2921447493 undo n:o < 0 state: running but idle
History list length 6

END OF INNODB MONITOR OUTPUT
============================
 

二、得出死锁原因

通过日志分析大致能定位到业务代码块,业务中存在的操作是针对文件表做先删除,后插入

于是乎会出现如下场景

object_id [ 2, 20,40,80,...] 普通索引

事务1:删除 object_id =10 的数据(数据不存在,于是事务1添加(2,20)的间隙锁 )

事务2:删除 object_id =11 的数据(数据不存在,于是事务2添加(2,20)的间隙锁,间隙锁非排斥锁 )

事务1:插入 object_id =10 的数据(获取当前间隙插入意向锁,由于当前位置存在事务2的间隙锁,于是事务1处理等待状态)

事务2:插入object_id =11 的数据(获取当前间隙插入意向锁,由于存在事务1的插入意向锁,于是进入等待,系统自动对加锁操作做死锁判断,识别到死锁,回滚事务1,事务2完成操作)

三、给出死锁解决方案

在删除数据前先查询数据是否存在,如果不存在则不执行删除,不执行删除则不会产生间隙锁

四、思考

  1. 凡是做修改和删除的操作尽量使用唯一性索引,唯一性索引不产生间隙锁,降低死锁发生的概率
  2. 如果需要对非唯一性索引数据做多次操作时,最后先判断数据是否存在,防止产生不必要的间隙锁引发死锁
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值