死锁排查的终点不是数据库,是业务代码里的加锁顺序

举报
yd_242310901 发表于 2026/10/28 01:26:07 2026/10/28
【摘要】 死锁的经典排查路径很成熟:捕获死锁图、找到阻塞链、确认锁类型和等待关系、处置并预防。但一个反复出现的经验是,死锁的根因很少在数据库配置里,而在业务代码的更新顺序里。一个订单系统高峰“假死”的复盘给出了很直接的结论:遇到死锁,别光看 trace 骂数据库,顺着 trace 里的 SQL 回到业务代码,把更新顺序统一,死锁自然就没了。两个事务以相反的顺序更新同一组行,是最典型的死锁形状:事务 A...

死锁的经典排查路径很成熟:捕获死锁图、找到阻塞链、确认锁类型和等待关系、处置并预防。但一个反复出现的经验是,死锁的根因很少在数据库配置里,而在业务代码的更新顺序里。

一个订单系统高峰“假死”的复盘给出了很直接的结论:遇到死锁,别光看 trace 骂数据库,顺着 trace 里的 SQL 回到业务代码,把更新顺序统一,死锁自然就没了。两个事务以相反的顺序更新同一组行,是最典型的死锁形状:事务 A 先锁订单再锁库存,事务 B 先锁库存再锁订单,彼此等待对方持有的锁。数据库能检测到死锁并回滚其中一个,但它无法替你决定业务上应该先锁谁。

预防层面的手段按成本从低到高排列:统一加锁顺序是最有效的,但需要跨代码库的约定和代码评审来维持;缩短事务范围、避免在事务中做远程调用和非必要 I/O,能显著降低持锁时间;设置合理的 lock_timeout 让等待方尽早失败而不是无限排队;降低隔离级别(在业务允许的前提下)可以减少间隙锁带来的冲突,但这是有语义取舍的动作,不能当成万能开关。

一个容易被忽略的实践是死锁的可观测性。PostgreSQL 的 deadlock_timeout 和死锁日志需要主动配置,很多团队在出问题之前根本没有开启详细记录。死锁不是“偶发故障”,它是并发模式的一个确定性信号。每一次死锁都在告诉你:某两条路径的加锁顺序不一致,或者某个事务持锁时间超出了设计预期。修死锁不是加一个重试了事,重试只是把冲突推迟到下一次。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。