最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
如何处理MySQL数据库中的死锁问题
时间:2026-07-10 10:53:52 编辑:袖梨 来源:一聚教程网
MySQL死锁发生后无需立即改代码,InnoDB会自动回滚代价较小事务并报错1213;应优先执行SHOW ENGINE INNODB STATUSG定位LATEST DETECTED DEADLOCK段,比对两事务SQL、HOLDS/WAITING锁信息及lock_mode类型,结合innodb_print_all_deadlocks开启全量日志分析,根因多为加锁顺序不一致或索引失效。
死锁发生后别急着改代码
MySQL 检测到死锁会自动回滚代价较小的事务,并抛出 Deadlock found when trying to get lock 错误(错误码 1213)。这不是故障,是 InnoDB 正常工作的表现——它主动打破了僵局。真正要做的,是定位哪两条 SQL 在抢同一组资源,以及为什么它们加锁顺序冲突。
用 SHOW ENGINE INNODB STATUSG 提取现场信息
这是排查死锁最直接、不可跳过的一步。执行后,在输出中只看 LATEST DETECTED DEADLOCK 段落,重点关注三块:
- 每个事务的
query id后紧跟着的实际 SQL,比如UPDATE t SET c = c + 1 WHERE id = 2 - 事务 (1) 的
HOLDS THE LOCK(S)和事务 (2) 的WAITING FOR THIS LOCK TO BE GRANTED—— 这告诉你谁先占了什么、谁在等什么 - 锁类型描述,如
RECORD LOCKS lock_mode X locks rec but not gap表示主键上的排他记录锁;若出现gap或next-key,说明涉及间隙锁,大概率和范围查询或非唯一索引有关
查不到日志?确认 innodb_print_all_deadlocks 是否开启
默认情况下,SHOW ENGINE INNODB STATUS 只保留最近一次死锁。如果线上频繁报错但日志里找不到上下文,大概率是没开全量记录。
- 临时开启(重启失效):
SET GLOBAL innodb_print_all_deadlocks = ON; - 永久生效需写入配置文件:
[mysqld]下加innodb_print_all_deadlocks = 1,并确保log_error路径可写 - 注意:开启后所有死锁都会追加进 error log,不清理可能撑爆磁盘
SQL 执行顺序不一致是最常见根因
很多团队把死锁归为“偶发”,其实只要两个事务更新同一组行但顺序不同,就一定会在足够高的并发下复现。
- 典型例子:
事务 A:UPDATE orders SET status=2 WHERE id=100;→UPDATE users SET last_order_id=100 WHERE id=5;
事务 B:UPDATE users SET last_order_id=101 WHERE id=5;→UPDATE orders SET status=2 WHERE id=101; - 解决方式不是加重试,而是强制统一操作顺序:比如永远先
orders,再users - 索引缺失也会放大问题:
WHERE user_id = ?若user_id无索引,InnoDB 会全表扫描并锁大量行,极易与其他事务交叉冲突
真正难处理的不是单次死锁,而是那些因间隙锁、长事务或 ORM 自动生成 SQL 顺序混乱导致的隐蔽冲突——它们不会立刻报错,但会在高并发时突然爆发。
相关文章
- 诛天剑侠橙色装备获取 07-10
- Premiere视频预览黑屏怎么办 07-10
- 微知库学生版app如何开启推送通知 07-10
- 如何查询中通快递快件单号 07-10
- 三口实训3ds是什么 07-10
- 腾讯视频官方在线观看正版清晰度高在哪看 07-10