死锁排查的终点不是数据库,是业务代码里的加锁顺序
【摘要】 死锁的经典排查路径很成熟:捕获死锁图、找到阻塞链、确认锁类型和等待关系、处置并预防。但一个反复出现的经验是,死锁的根因很少在数据库配置里,而在业务代码的更新顺序里。一个订单系统高峰“假死”的复盘给出了很直接的结论:遇到死锁,别光看 trace 骂数据库,顺着 trace 里的 SQL 回到业务代码,把更新顺序统一,死锁自然就没了。两个事务以相反的顺序更新同一组行,是最典型的死锁形状:事务 A...
死锁的经典排查路径很成熟:捕获死锁图、找到阻塞链、确认锁类型和等待关系、处置并预防。但一个反复出现的经验是,死锁的根因很少在数据库配置里,而在业务代码的更新顺序里。
一个订单系统高峰“假死”的复盘给出了很直接的结论:遇到死锁,别光看 trace 骂数据库,顺着 trace 里的 SQL 回到业务代码,把更新顺序统一,死锁自然就没了。两个事务以相反的顺序更新同一组行,是最典型的死锁形状:事务 A 先锁订单再锁库存,事务 B 先锁库存再锁订单,彼此等待对方持有的锁。数据库能检测到死锁并回滚其中一个,但它无法替你决定业务上应该先锁谁。
预防层面的手段按成本从低到高排列:统一加锁顺序是最有效的,但需要跨代码库的约定和代码评审来维持;缩短事务范围、避免在事务中做远程调用和非必要 I/O,能显著降低持锁时间;设置合理的 lock_timeout 让等待方尽早失败而不是无限排队;降低隔离级别(在业务允许的前提下)可以减少间隙锁带来的冲突,但这是有语义取舍的动作,不能当成万能开关。
一个容易被忽略的实践是死锁的可观测性。PostgreSQL 的 deadlock_timeout 和死锁日志需要主动配置,很多团队在出问题之前根本没有开启详细记录。死锁不是“偶发故障”,它是并发模式的一个确定性信号。每一次死锁都在告诉你:某两条路径的加锁顺序不一致,或者某个事务持锁时间超出了设计预期。修死锁不是加一个重试了事,重试只是把冲突推迟到下一次。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)