Взаимоблокировка / конфликт блокировок (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;- Граф получен — две транзакции блокируют ресурсы в обратном порядке
- Много транзакций скапливается на одной строке/таблице (hotspot)
- Есть широкие блокировки диапазонов (блокируется много строк)
Использует ли блокирующий запрос индекс?
Без индекса 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 без индекса блокирует больше строк, чем нужно, и делает взаимоблокировки гораздо вероятнее.
Первопричина: горячая точка (hotspot)
Много транзакций одновременно скапливается на одном ресурсе, например строке/ключе счётчика.