数据库死锁(Deadlock)是指两个或多个事务相互持有对方所需的锁,导致都无法继续执行。死锁无法 100% 彻底消除,但可以通过设计和运维手段大幅降低发生概率,并在发生后快速恢复。
下面从 原理 → 避免策略 → 实战建议 系统说明。
死锁通常同时满足以下条件:
避免死锁的核心思路:破坏以上至少一个条件。
所有事务按相同顺序访问表和行
❌ 容易死锁:
事务A:update 用户 → update 订单
事务B:update 订单 → update 用户
✅ 避免方式:
统一:先用户,后订单
这是最有效、工程上最常用的方法
事务越长,持锁越久,死锁概率越高。
✅ 建议:
❌ 错误示例:
BEGIN;
UPDATE account SET balance=balance-100 WHERE id=1;
-- 等待第三方支付回调
UPDATE account SET balance=balance+100 WHERE id=2;
COMMIT;
LOCK TABLE
SELECT ... FOR UPDATE(无索引)
✅ 确保 WHERE 条件走索引:
SELECT * FROM orders WHERE id = 1 FOR UPDATE;
| 隔离级别 | 死锁风险 |
|---|---|
| READ UNCOMMITTED | 低 |
| READ COMMITTED | 中 |
| REPEATABLE READ | 高 |
| SERIALIZABLE | 最高 |
✅ MySQL 默认 RR,可评估是否降到 RC
✅ Oracle 默认 RC,死锁较少
典型场景:
✅ 优化方案:
UPDATE stock
SET count = count - 1
WHERE id = 1 AND count > 0;
数据库自带机制:
innodb_lock_wait_timeout✅ 应用层要:
死锁是“正常异常”,不是 bug。
for (int i = 0; i < 3; i++) {
try {
doTransaction();
break;
} catch (DeadlockException e) {
sleep(50 * (i+1));
}
}
SHOW ENGINE INNODB STATUS;
重点看:
LATEST DETECTED DEADLOCKSELECT * FROM sys.dm_tran_locks;
统一顺序访问,缩短事务时间
索引避免全表锁,热点拆分降竞争
死锁不是故障,重试即可恢复
如果你愿意,可以:
我可以帮你做针对性死锁分析。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。