news 2026/6/10 21:32:02

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/6/10 13:03:37

Nodejs毕设选题推荐:基于nodejs的药膳食堂点餐系统的设计与实现基于Node+Vue药膳食堂点餐系统设计与实现【附源码、mysql、文档、调试+代码讲解+全bao等】

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

作者头像 李华
网站建设 2026/6/10 14:53:01

nt!PiProcessNewDeviceNode对节点PCI0的处理nt!PpQueryDeviceID

nt!PiProcessNewDeviceNode对节点PCI0的处理nt!PpQueryDeviceID0: kd> kc# 00 nt!PiProcessNewDeviceNode 01 nt!PipProcessDevNodeTree 02 nt!PipDeviceActionWorker 03 nt!PipRequestDeviceAction 04 nt!IopInitializeBootDrivers 05 nt!IoInitSystem 06 nt!Phase1Initial…

作者头像 李华
网站建设 2026/6/9 22:03:41

2026转行要趁早!网络安全行业人才缺口大,企业招聘需求正旺!

网络安全行业具有人才缺口大、岗位选择多、薪资待遇好、学历要求不高等优势&#xff0c;对于想要转行的人员来说&#xff0c;是一个非常不错的选择。 人才缺口大 网络安全攻防技术手段日新月异&#xff0c;特别是现在人工智能技术飞速发展&#xff0c;网络安全形势复杂严峻&am…

作者头像 李华
网站建设 2026/6/10 15:25:09

【课程设计/毕业设计】基于nodejs的宠物医院爱宠信息管理系统的设计与实现宠物医院预约挂号网【附源码、数据库、万字文档】

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

作者头像 李华
网站建设 2026/6/10 21:27:57

ChatGPT写的论文怎么降AI率?AIGC生成内容的检测规避方法

ChatGPT写的论文怎么降AI率AIGC生成内容的检测规避方法的核心问题是什么&#xff1f;在深入探讨这个话题之前&#xff0c;我们需要先理解问题的本质。ChatGPT写的论文怎么降AI率&#xff0c;这是很多同学在处理论文时都会遇到的问题。 AIGC检测系统的工作原理是分析文本的统计学…

作者头像 李华