DBAtlas · Атлас эксплуатации баз данных

Взаимоблокировка / конфликт блокировок (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)

Много транзакций одновременно скапливается на одном ресурсе, например строке/ключе счётчика.

Открыть в DBAtlas →