业务中遇到的一次死锁错误,并附解决方案;

今天在测试线程池死锁时,想起来当初在公司中遇到的一次数据库死锁经历;

 

1.起因是有一天我看服务器日志,出现了死锁日志,并说明情况以前就发生过,不过概率很小;

2.定位出现死锁问题代码,发现是mq消费端,其中大致的业务是(消费一个消息,该消息会携带多个商品id及处理方式,然后需要for循环进行查询更新操作)

3.于是想问题出现原因,因为数据库使用的mysql的innodb引擎,所以在处理更新数据时会使用到行级的排他锁

(1)想到是否是因为处理速度太慢,引发锁等待超时?(测试加日志分析其实处理并不慢,达不到超时的时间)

(2)想到是否由于循环依赖锁资源产生;

4.查看业务和测试得出的却是上述第二种情况:原因就是

当并发的接受消息后,并发处理期间,出现了 1事务中更新A  然后更新B操作,此时2事务中 更新B 更新A操作;

此时如果正好1事务在更新A后,2事务更新B,那么A B都占有锁资源,随后1事务想要更新B,2事务想要更新A,那么发生死锁;

 

5.查明问题原因后就好解决了:

(1)最简单快速方案,将消费消息的商品顺序进行排序,那么就会避免出现循环依赖死锁问题,只可能出现等待锁超时问题;

(2)将mq消费线程设置为1,但是消费能力肯定下降,要依照业务需求来定;

(3)使用分布式锁方式,来禁止相同商品并发消费,也是依照业务尝试使用;

(4)重构业务代码,将整体事务缩小执行时间,避免出现死锁;

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值