news 2026/5/2 13:52:51

MySQL死锁排查与预防实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
MySQL死锁排查与预防实战

前言

线上日志里突然出现大量这个错误:

Deadlock found when trying to get lock; try restarting transaction

死锁是MySQL高并发场景下的常见问题。偶尔一两次可以通过业务重试解决,但如果频繁出现,就需要从根本上排查和优化。

这篇整理MySQL死锁的排查方法和预防策略。


一、查看死锁信息

MySQL有个命令能看到最近一次死锁的详情:

SHOWENGINEINNODBSTATUS\G

输出很长,找LATEST DETECTED DEADLOCK这部分:

*** (1) TRANSACTION: UPDATE orders SET status = 'paid' WHERE id = 1001 *** (1) HOLDS THE LOCK(S): -- 持有orders表的锁 *** (1) WAITING FOR THIS LOCK: -- 等inventory表的锁 *** (2) TRANSACTION: UPDATE inventory SET quantity = quantity - 1 WHERE product_id = 2001 *** (2) HOLDS THE LOCK(S): -- 持有inventory表的锁 *** (2) WAITING FOR THIS LOCK: -- 等orders表的锁 *** WE ROLL BACK TRANSACTION (2)

经典的死锁场景:事务A锁了orders等inventory,事务B锁了inventory等orders,互相等。

二、分析死锁原因

知道是哪两个SQL了,回去翻代码。

原来下单逻辑里有两种调用顺序:

// 路径A:先改订单再扣库存updateOrderStatus(orderId,"paid");decreaseInventory(productId,1);// 路径B:先扣库存再改订单(另一个接口)decreaseInventory(productId,1);updateOrderStatus(orderId,"paid");

两个接口都在事务里,刚好并发了就死锁。

三、解决方案

最直接的办法:统一加锁顺序

不管哪个接口,都先操作orders再操作inventory(或者反过来,总之要一致)。

// 统一顺序:先orders后inventory@TransactionalpublicvoidprocessOrder(longorderId,longproductId){updateOrderStatus(orderId,"paid");// 永远先锁ordersdecreaseInventory(productId,1);// 再锁inventory}

如果涉及多条记录,按ID排序:

List<Long>ids=Arrays.asList(id1,id2,id3);Collections.sort(ids);for(Longid:ids){lockAndProcess(id);}

四、间隙锁导致的死锁

还有一种更诡异的死锁,两个事务操作的都不是同一行数据。

这通常是间隙锁的问题。RR隔离级别下,SELECT ... FOR UPDATE如果没命中数据,会锁一个"间隙"。

比如user_id有1、5、10三条记录:

-- 事务ASELECT*FROMordersWHEREuser_id=3FORUPDATE;-- 没有user_id=3的数据,但会锁住(1,5)这个间隙-- 事务BSELECT*FROMordersWHEREuser_id=7FORUPDATE;-- 锁住(5,10)这个间隙-- 然后两边各自INSERT-- 事务A想插入user_id=6,要等(5,10)的间隙锁-- 事务B想插入user_id=4,要等(1,5)的间隙锁-- 死锁

解决办法:

  1. 改用RC隔离级别(间隙锁少很多,但要注意幻读)
  2. 用唯一索引精确查询,避免范围锁
SETSESSIONTRANSACTIONISOLATIONLEVELREADCOMMITTED;

五、缩小事务范围

还有个常见问题是事务太长。事务越长,持有锁的时间越久,死锁概率越高。

// 这种写法不好@Transactionalpublicvoidprocess(){queryData();// 查数据callExternalApi();// 调外部接口,可能很慢updateDatabase();// 更新数据库}// 改成这样publicvoidprocess(){queryData();callExternalApi();// 外部调用放事务外面updateInTransaction();}@TransactionalpublicvoidupdateInTransaction(){updateDatabase();// 只有真正需要事务的操作}

六、监控与告警

建议加上监控:

# 简单脚本,每分钟检查死锁次数DEADLOCKS=$(mysql -e"SHOW GLOBAL STATUS LIKE 'Innodb_deadlocks'"|awk'NR==2{print $2}')echo"$(date)deadlocks:$DEADLOCKS">>/var/log/deadlock.log

配合Prometheus的话:

-alert:MySQLDeadlockexpr:increase(mysql_global_status_innodb_deadlocks[5m])>0for:1m

死锁次数涨了就告警,别等业务反馈才知道。

七、业务层重试

有些场景死锁确实很难完全避免,那就在业务层做重试:

intretry=3;while(retry-->0){try{doTransaction();break;}catch(DeadlockExceptione){if(retry==0)throwe;Thread.sleep(100);// 等一下再试}}

MySQL检测到死锁会立即回滚一个事务,不会一直卡着,所以重试通常能成功。


总结

死锁本质是资源竞争问题,预防比解决更重要:

方法效果
统一加锁顺序最有效,从根本上避免死锁
缩小事务范围减少锁持有时间
合理使用索引减少锁的范围
降低隔离级别减少间隙锁(RC级别)
业务层重试兜底方案

记住两点:统一加锁顺序缩小事务范围,能解决大部分死锁问题。


有问题评论区交流。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/17 17:11:26

AI辅助设计炸裂!PanelAI前后端原型图美到“吊打99%人工”,开发者危机感爆棚:未来人机融合时代要来了?

大家好&#xff0c;真的看得既兴奋又emo。作为一个天天用AI工具写代码、搞设计的开发者&#xff0c;看到这段内容瞬间破防又共鸣&#xff0c;今天赶紧整理出来和大家分享。 视频核心内容&#xff1a; 熊哥最近在全力优化PanelAI的前端和后端设计。以前靠自己和团队肝&#xff…

作者头像 李华
网站建设 2026/4/24 0:14:55

Nodejs毕设项目推荐-基于Node+Vue药膳食堂点餐系统设计与实现基于nodejs的药膳食堂点餐系统的设计与实现【附源码+文档,调试定制服务】

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2026/5/1 14:00:14

三角函数完备

这两个图片的内容紧密相关&#xff0c;它们共同构建了现代信号处理和函数分析的基石。简单来说&#xff0c;第一张图&#xff08;2.4.1&#xff09;提供了理论武器&#xff08;幂函数是完备的&#xff09;&#xff0c;第二张图&#xff08;2.4.4&#xff09;则利用这个武器攻克…

作者头像 李华
网站建设 2026/4/30 0:22:37

Chebyshev Polynomials 与现代计算

这是一个非常敏锐且切中要害的问题&#xff01; 你完全抓住了重点&#xff1a;切比雪夫多项式 (Chebyshev Polynomials) Tn(x)T_n(x)Tn​(x) 的正交区间&#xff08;以及最佳逼近性质的“主场”&#xff09;确实是在 [−1,1][-1, 1][−1,1] 上。 既然如此&#xff0c;计算机如…

作者头像 李华
网站建设 2026/5/1 12:29:58

毕业论文神器!实力封神的AI论文软件 —— 千笔写作工具

你是否曾为论文选题而焦虑不已&#xff1f;是否在撰写过程中因思路混乱而反复推翻&#xff1f;又是否因为查重率过高而心力交瘁&#xff1f;面对这些学术写作的常见难题&#xff0c;很多同学都感到无从下手。而如今&#xff0c;一款专为学生打造的AI论文写作工具——千笔AI&…

作者头像 李华
网站建设 2026/5/1 1:42:57

springboot基于springboot的网上商城购物系统-vue可视化 商家

目录 基于SpringBoot和Vue的网上商城购物系统&#xff08;商家端&#xff09;摘要 开发技术源码文档获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01; 基于SpringBoot和Vue的网上商城购物系统&#xff08;商家端&#xff09;摘要 系统概述 该系统…

作者头像 李华