mysql死锁查询

背景查监控发现线上时不时出现财务报表数据更新失败情况,追查日志发现,更新失败全部由于数据库死锁导致,日志报错“Deadlock found when trying to get lock”,经DBA查线上数据库日志,发现线上其他库表也存在死锁情况。 为了更系统的分析问题,将从问题定位、死锁成因分析,mysql锁知识这几个方面来展开讨论。引起死锁的case【定位问题】通过异常监控查看对应...
摘要由CSDN通过智能技术生成

背景

查监控发现线上时不时出现财务报表数据更新失败情况,追查日志发现,更新失败全部由于数据库死锁导致,日志报错“Deadlock found when trying to get lock”,经DBA查线上数据库日志,发现线上其他库表也存在死锁情况。 为了更系统的分析问题,将从问题定位、死锁成因分析,mysql锁知识这几个方面来展开讨论。

引起死锁的case

【定位问题】通过异常监控查看对应时间点目标系统的日志,发现不同时间的报错点都是由于死锁导致。 找到代码中的报错的位置,查看代码逻辑,发现发生死锁的代码处有使用事务(代码中没有明确指定事务隔离级别,默认RR),事务中有两处DML操作,如下:

#同一事物
#操作一:
insert into finance_report_info(order_type,sale_channel_no,sale_channel_name,exhibition_channel_no..)
values("q","a","a","cc");

#操作二:
UPDATE finance_report_info
SET is_show = "NO"
WHERE order_no = ? and warranty_no = ? and insurant_id = ? and acceptance_date > ?

 

这时候找到DBA帮忙查询死锁的日志,部分日志如下;

 

日志没有截全,只显示了发生死锁时事务1的日志。从日志中可以分析出,死锁时事务A正在等待锁的sql是“update finance_report_info SET is_show = "NO" WHERE order_no = 'RS_YGUA201901301506582205c' and warranty_no = '8024990030961928' and insurant_id = 63943 and acceptance_date > '2019-02-22 04:04:21'”, 事务A正在等待主索引的X锁。 事务B的日志和事务A一致,事务B正在等待锁的sql是“UPDATE finance_report_info SET is_show = "NO" WHERE order_no = 'RS_YGUA201901291711532907b' and warranty_no = '8024990030959368' and insurant_id = 62393 and acceptance_date > '2019-02-22 04:04:21'“”。

【死锁日志分析】根据死锁记录的结果,可以看出确实是这两个语句发生了死锁,且锁冲突发生在主键索引上。那么,为什么两个sql语句会存在锁冲突呢?

查看线上数据库的finance_report_info表结构发现,发生死锁冲突的update语句的匹配条件没有加索引,这时候如果执行更新操作的话,走的是锁表(InnoDB的行锁是基于索引实现的,如果不通过索引访问数据,InnoDB会使用表锁)。 这时候综合代码分析,当多个事务并发执行的时候,在

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值