mysql死锁发生时,需通过错误日志、innodb status、information_schema.lock_waits及django异常码1213精准定位谁、在哪、为何卡住,而非仅避免;关键在于可复现、可归因、可收敛。
直接看 mysql 错误日志里的 deadlock found when trying to get lock
只要 django 报出这个错误,就说明死锁已经发生,且 mysql 已回滚了某个事务。关键不是“怎么避免”,而是“这次是谁、在哪、为什么卡住”。log_error 路径可通过 show variables like 'log_error'; 查到,常见位置是 /var/log/mysql/error.log。用 tail -f /var/log/mysql/error.log | grep -i "deadlock" 实时盯住,一出错立刻捕获上下文。
注意:默认只记最近一次死锁;要记录全部,必须在 MySQL 配置里加 innodb_print_all_deadlocks = ON,否则历史死锁信息会被覆盖。
用 SHOW ENGINE INNODB STATUS\G 提取现场快照
这个命令输出很长,但只盯 LATEST DETECTED DEADLOCK 区块就够了。它会明确告诉你:
- 两个事务各自的
TRANSACTION ID和执行的 SQL(比如UPDATE accounts SET balance = ... WHERE id = 1) - 哪个事务持有了什么锁(
HOLDS THE LOCK(S)),哪个在等什么锁(WAITING FOR THIS LOCK TO BE GRANTED) - 被 MySQL 主动回滚的是哪一个(最后一行通常写
WE ROLL BACK TRANSACTION (1))
别跳过“锁住的索引”字段 —— 如果看到 index PRIMARY 是正常行锁,但出现 index GEN_CLUST_INDEX 或没命中索引的 gap lock,说明查询没走索引,锁范围远超预期。
Django 层捕获异常时必须检查 exc.args[0] 是否为 1213
Django 的 DatabaseError 不区分死锁和其他锁等待超时,仅靠字符串匹配 “Deadlock” 容易漏判或误判。真实死锁的底层错误码固定是 1213,而超时是 1205 或其他。
正确做法:
try:
with transaction.atomic():
# 你的 update/select_for_update 操作
pass
except DatabaseError as exc:
if exc.args and exc.args[0] == 1213: # 真死锁
logger.warning("Deadlock detected: %s", str(exc))
raise # 或按需重试
else:
raise
不这么做,你就没法把死锁从普通锁等待里筛出来,监控和统计全失真。
查 information_schema.innodb_lock_waits 看实时阻塞链
死锁刚发生后可能还没写进日志,或者你想确认“现在有没有正在卡住的事务”,就跑这条 SQL:
SELECT r.trx_id AS waiting_trx_id,
r.trx_mysql_thread_id AS waiting_thread,
r.trx_query AS waiting_query,
b.trx_id AS blocking_trx_id,
b.trx_mysql_thread_id AS blocking_thread,
b.trx_query AS blocking_query
FROM information_schema.innodb_lock_waits w
INNER JOIN information_schema.innodb_trx b ON b.trx_id = w.blocking_trx_id
INNER JOIN information_schema.innodb_trx r ON r.trx_id = w.requesting_trx_id;
结果里每行就是一个“谁在等谁”。如果 waiting_query 和 blocking_query 都来自你的 Django view 或 task,基本就能锁定是哪段代码在交叉加锁。特别注意 trx_state = 'LOCK WAIT' 的事务 —— 它们未必已死锁,但已是高危状态。
真正容易被忽略的点:死锁不是代码 bug,而是并发下资源争抢的必然现象;定位目标不是“消灭死锁”,而是让每次死锁都可复现、可归因、可收敛到少数几个确定路径上 —— 否则你永远在修幻觉。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











