我的物联网项目(二十七) 分布式锁粗心导致大量阻塞

2018-07-20 15:41:28

有天项目中某个业务出现了异常,查询相关日志显示如下:

### Error updating database.  Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction

吓了大跳,居然还有锁时间过长导致后面的业务等待时间较长断开连接抛异常,看了下数据库控制台基本全黄,都是些执行时间较长正在执行的进程。

dddd11.png里面详细的SQL,继续点进去看看执行计划

dddd22.png从执行计划上看,扫码行数其实并不多的,所以还要从具体的业务场景去分析问题。


找到执行这条SQL的业务代码,了解当时的业务场景:

t_affairsevent事件表

dddd33.png

简单描述下,这个事件表是用来做分布式事务,利用分布式调度来轮询,然后处理相关业务,具体可以看前面写过 我的物联网项目(八) 简单分布式调度,前面有讲到过利用setNX()来实现分布式锁,每次通过setNX()同一个标识,比如id来抢占锁,前面的业务场景没有问题,但是在这个业务场景里面问题来了,因为同时3个调度来分别执行id为1,2,3的3条记录都可以抢的到,然后都去执行如下SQL:

update t_partner_bymonth set .... where partnerId=10001 ,这样的话会导致多个SQL线程同时在执行同一记录,而且本身update就带锁行,所以导致执行速度巨慢甚至阻塞。

高并发update时,最先获得锁的会优先执行,其它几条处于行锁等待状态,等第一个执行完毕,行锁释放,由下一条语句获取锁进行更新,当其它会话等待的时间达到innodb_lock_wait_timeout(默认是50秒),这些update就会断开,不再执行。

像这种业务场景,将锁标识换成partnerId就可以避免刚才那种情况。

(微信打赏)

(支付宝打赏)
原创不易,谢谢赞赏。你的支持就是我的动力,我会更加努力。

最近平台有人员反应了几个问题:1.商家充值记录有时候莫名其妙存在充值后的重复数据记录。2.开发人员无意中提了一次我们的feign负载均衡有时候会负载到两台集群服务器都会执行。3.定时调度去执行当日表移单要历史表,发现存储过程被调用了两次。

当今主流云服务器代金劵,优惠折扣最大力度推荐。

阿里云产品1888元服务器代金券大礼包免费领取。

阿里云服务器低门槛上云捷径,普惠上云,云服务器1核1G仅需293元/年。

企业级高性能实例,限时2-5折,限首次购买ECS用户参与,限购4台。

腾讯云代金券新用户满200减150 满500减375 满1000减750 满2000减1500。

腾讯云服务器,数据库热卖云产品3折起,爆品低至1折。

腾讯云业界领先的性价比,0.57元/天起,关注最新活动,免费体验产品。