hostprofi.ru
Подобрать хостинг
Термин·буква D

Deadlock

краткое определение

Дедлок (deadlock) — ситуация взаимной блокировки в многопоточных системах или СУБД, когда два или более процесса удерживают ресурсы и одновременно ожидают освобождения ресурсов друг друга. Приводит к зависанию всех участвующих процессов.

Дедлок (deadlock, взаимная блокировка) — ситуация, при которой два или более процесса или транзакции находятся в состоянии циклического ожидания: каждый удерживает ресурс, необходимый следующему, и ждёт освобождения ресурса, удерживаемого предыдущим. Ни один не может продолжить работу без внешнего вмешательства.

Четыре условия Коффмана

Дедлок возможен только при одновременном выполнении четырёх условий (Coffman conditions, 1971):

  1. Mutual Exclusion (взаимное исключение) — ресурс используется только одним процессом одновременно.
  2. Hold and Wait (удержание и ожидание) — процесс удерживает один ресурс и ожидает освобождения другого.
  3. No Preemption (нет вытеснения) — ресурс нельзя принудительно забрать у процесса.
  4. Circular Wait (кольцевое ожидание) — цепочка ожидания замкнута: A ждёт B, B ждёт C, C ждёт A.

Нарушение любого одного условия предотвращает дедлок.

Дедлоки в PostgreSQL

PostgreSQL автоматически обнаруживает дедлоки и прерывает одну из транзакций с ошибкой ERROR: deadlock detected. Параметр deadlock_timeout (по умолчанию 1 секунда) — время ожидания блокировки до проверки на дедлок. Пример ошибки в логах:

ERROR: deadlock detected
DETAIL: Process 12345 waits for ShareLock on transaction 678;
        blocked by process 23456.
        Process 23456 waits for ShareLock on transaction 789;
        blocked by process 12345.
HINT: See server log for query details.
CONTEXT: while updating tuple (0,42) in relation "orders"

Типичная причина дедлоков в PHP/Python приложениях: параллельные транзакции обновляют строки в разном порядке. Транзакция 1: UPDATE orders SET status='paid' WHERE id=5; затем UPDATE orders SET status='paid' WHERE id=10. Транзакция 2 одновременно: UPDATE orders SET status='paid' WHERE id=10; затем UPDATE orders SET status='paid' WHERE id=5. Оба заблокируют друг друга. Решение: всегда обрабатывать записи в одном и том же порядке (по первичному ключу по возрастанию).

Дедлоки в MySQL/InnoDB

MySQL InnoDB также обнаруживает дедлоки автоматически. Последний зафиксированный дедлок: SHOW ENGINE INNODB STATUS → секция «LATEST DETECTED DEADLOCK». InnoDB выбирает жертву — транзакцию с наименьшей стоимостью отката. Параметр innodb_deadlock_detect (MySQL 5.7.15+): можно отключить при высокой нагрузке, если использовать innodb_lock_wait_timeout как альтернативу.

История

Формальное описание дедлоков и четыре необходимых условия сформулировал Эдвард Коффман (Edward Coffman) в 1971 году. Проблема дедлоков исследовалась с первых многозадачных ОС 1960-х. «Задача обедающих философов» Дейкстры (1965) — классический пример потенциального дедлока: 5 философов, 5 вилок, каждый берёт сначала левую, потом правую — возможно кольцевое ожидание.

Профилактика дедлоков в хостинге

На серверах с PostgreSQL или MySQL дедлоки проявляются при пиковой нагрузке на нагруженных интернет-магазинах. Диагностика в PostgreSQL: SELECT * FROM pg_locks l JOIN pg_stat_activity a ON l.pid = a.pid WHERE NOT granted; — незавершённые блокировки в реальном времени. Профилактика:

  • Использовать короткие транзакции — удерживать блокировки минимальное время.
  • Обновлять записи в детерминированном порядке — всегда по возрастанию id.
  • Минимизировать SELECT FOR UPDATE — брать только те строки, которые реально нужно изменить.
  • Оптимистичные блокировки (versioning через поле updated_at) вместо пессимистичных — конфликт обнаруживается при коммите, не при старте транзакции.
  • Мониторинг через Prometheus: метрика pg_stat_activity_count{state="waiting"}.

Другие термины

Deadlock — что это, определение и как работает | Справочник — hostprofi.ru