数据库死锁咋查?解决死锁问题的那些方法和思路分享
- 问答
- 2026-01-19 06:19:38
- 3
说到数据库死锁,这确实是让很多开发者和DBA头疼的问题,想象一下,两个事务就像两个人在一条很窄的走廊里相遇,每个人都等着对方让路,结果谁都过不去,就这么僵持住了,数据库里的死锁也是这个道理,下面我们就来聊聊,怎么发现它,以及怎么解决它。
第一部分:怎么知道发生了死锁?(排查与诊断)
你得先意识到系统可能出现了死锁,常见的症状有:应用程序的某个功能突然变得非常慢,或者直接卡住没反应了;数据库监控图上可能看到有会话(Session)长时间处于“等待”状态,CPU使用率却不高。
当怀疑是死锁时,可以从以下几个地方找证据:
-
数据库错误日志:这是最直接的地方,绝大多数数据库(比如MySQL, SQL Server等)在检测到死锁时,都会在自身的错误日志中记录下详细的信息,以MySQL为例,当你打开死锁日志记录(设置参数
innodb_print_all_deadlocks = ON),一旦发生死锁,日志里就会记录下导致死锁的两个事务当时正在执行的SQL语句,以及它们各自已经持有了哪些锁、又在等待哪个锁,这份日志是分析死锁根源的“第一现场”。 -
系统视图或表:数据库通常会提供一些动态性能视图,让你能实时查看当前的锁等待情况,比如在MySQL中,可以查询
information_schema.INNODB_TRX来查看当前所有事务的状态,查询information_schema.INNODB_LOCKS查看当前的锁信息,查询information_schema.INNODB_LOCK_WAITS查看锁的等待关系,通过关联这些表,你就能清晰地画出一个“谁在等谁”的关系图,从而定位死锁,Oracle数据库的v$session、v$lock等视图也是类似的用途。 -
数据库监控工具:很多第三方的或云服务商提供的数据库监控工具(例如Percona Monitoring and Management, 阿里云的DAS等)会有更直观的界面,它们能自动采集锁等待和死锁的信息,并用图表展示出来,你甚至可以直接在工具上看到死锁的详细报告和分析,比自己查日志和系统视图要方便很多。

第二部分:解决死锁的常见方法和思路
找到死锁的原因后,接下来就是如何解决和预防,死锁一旦发生,数据库本身会有一个“死锁检测”机制,它会自动选择一个“牺牲者”(通常是根据规则选择回滚代价最小的事务),将其回滚,从而让另一个事务得以继续,我们的目标,是尽量减少甚至避免死锁的发生。
-
保持事务简短小巧:这是最最重要的一条原则,一个事务里包含的操作越多,执行时间越长,它持有锁的时间也就越长,与其他事务发生冲突的几率就越大,要养成好习惯:事务里只包含最必要的数据库操作,并且尽快提交或回滚事务,不要在事务里进行文件IO、网络调用或者让用户输入等耗时操作。
-
约定一致的访问顺序:这是解决死锁的一个经典思路,如果多个事务都需要操作多个资源(比如A表和B表),我们强制规定所有事务都必须按照相同的顺序来访问这些资源,比如必须先访问A表,再访问B表,这样就能从根本上避免循环等待的发生,就像交通规则要求所有车都靠右行驶一样,大家都遵守规则,就不会迎头相撞。

-
为操作选择合适的“锁的力度”:如果业务允许,尽量使用更“轻量”的锁,在能使用乐观锁(通常是通过在表加一个版本号字段来实现)的情况下,就不要用悲观锁(
SELECT ... FOR UPDATE),如果一定要用悲观锁,也要考虑是否真的需要锁住所有符合条件的行,有时候可能只需要锁住关键的一行就行。 -
降低事务的隔离级别:数据库的事务隔离级别越高(如“可重复读”),它为了保持数据一致性而加的锁就越多,持有时间也可能越长,在某些对数据绝对一致性要求不是那么极致的业务场景下,可以考虑将隔离级别适当调低(如“读已提交”),这样可以减少锁冲突,但这么做之前一定要评估清楚对业务的影响。
-
为查询建立合适的索引:这一点非常关键但容易被忽略,如果一个
UPDATE或DELETE语句的WHERE条件字段没有索引,数据库可能就会退而求其次,去锁住整个表(表锁)或者一大片范围内的数据(间隙锁),这大大增加了与其他事务发生冲突的概率,通过为查询条件建立合适的索引,可以让数据库更精准地只锁住需要的数据行,显著降低死锁风险。 -
重试机制:尽管我们做了很多优化,但在高并发场景下,死锁可能还是无法完全避免,这时,在应用程序代码里加入重试逻辑就是一个很实用的容错方法,当捕获到数据库抛出的死锁错误(比如MySQL的错误码1205)后,不要立刻给用户报错,可以让程序等待一小段随机时间,然后自动重新执行整个事务,短暂的等待后,资源竞争情况已经改变,重试很大概率会成功。
处理死锁就是一个“先发现、后分析、再根治”的过程,核心思路就是缩短锁的持有时间、减少锁的竞争范围、让资源访问变得有秩序可循,平时多关注数据库的日志和监控,对慢SQL进行优化,就能防患于未然。
本文由盘雅霜于2026-01-19发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:https://haoid.cn/wenda/83502.html
