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

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

### 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就可以避免刚才那种情况。

 

 
posted @   心灵之火  阅读(519)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· [AI/GPT/综述] AI Agent的设计模式综述
点击右上角即可分享
微信分享提示