死锁/锁冲突(ORA-00060、1213、40P01)
遇到了死锁(Oracle ORA-00060、MySQL 1213、PG 40P01、MSSQL 1205)。捕获死锁图,弄清模式,防止再次发生。死锁通过设计来解决——目标是降低其发生频率。
先捕获死锁图
是哪两个(或更多)会话、哪些资源、哪些锁模式发生了冲突?没看到这些之前不要盲目修复。
-- Check the trace file referenced in the alert log (deadlock graph). For history:
SELECT * FROM dba_hist_active_sess_history WHERE event LIKE 'enq: TX%' ORDER BY sample_time DESC FETCH FIRST 20 ROWS ONLY;- 已拿到死锁图——两个事务以相反顺序锁定资源
- 大量事务堆积在单行/单表上(热点)
- 存在大范围锁(许多行被锁定)
加锁的查询是否使用了索引?
没有索引时,UPDATE/DELETE 为满足 WHERE 子句会锁定大量行(甚至整张表)→ 这是死锁的来源之一。检查它的执行计划。
EXPLAIN <the UPDATE/DELETE involved in the deadlock>; -- type=ALL means a full scan, no index- 没有索引/在做全表扫描
- 有索引,但仍然冲突
根本原因:加锁顺序相反
死锁最常见的原因:两个事务以不同顺序访问资源。A→B 和 B→A 同时发生时,就会死锁。
根本原因:缺少索引 → 大范围锁
没有索引的 UPDATE/DELETE 锁定的行多于必要,大大增加死锁的可能性。
根本原因:热点
大量事务同时堆积在计数器行/键这类单一资源上。