linuxlab.io
Учебники▾
  • Линукс и сети
    Файловая система, процессы, TCP/IP, BGP и OSPF
    →
  • Terraform и IaC
    HCL, state, plan/apply на sandbox LocalStack
    →
  • Git и GitHub
    Объектная модель, plumbing, ветвление, GitHub Actions
    →
Все учебники →
ЦеныО платформеВойтиСоздать аккаунт
/
Intro
Lessons
Footer
linuxlab-УчебникиЦеныО платформеКонфиденциальность и куки
Copyright © 2026 LinuxLab. Все права защищены.
linuxlab.io
Учебники▾
  • Линукс и сети
    Файловая система, процессы, TCP/IP, BGP и OSPF
    →
  • Terraform и IaC
    HCL, state, plan/apply на sandbox LocalStack
    →
  • Git и GitHub
    Объектная модель, plumbing, ветвление, GitHub Actions
    →
Все учебники →
ЦеныО платформеВойтиСоздать аккаунт
/
  • Введение
  • Главы
  • How it worksскоро
  • Уроки
  • База знаний
  • Собеседование
home/postgres/kb/Блокировки/deadlocks

kb/locks ── Блокировки ── intermediate

Взаимоблокировки (deadlock)

Deadlock - цикл в графе ожидания: каждая транзакция ждёт ту, что ждёт её. PostgreSQL находит его через deadlock_timeout (1 с) и откатывает одну транзакцию с ошибкой 40P01. Лечится единым порядком блокировок.

view as markdownaka: deadlock, deadlock-detected, wait-for-graph

Очередь блокировок честная, поэтому обычное ожидание рано или поздно разрешается. Исключение - когда дождаться нельзя в принципе: A держит строку 1 и хочет строку 2, B держит строку 2 и хочет строку 1. Это взаимоблокировка, и сама она не рассосётся.

Граф ожидания

Вершины - транзакции, ребро A → B значит «A ждёт то, что держит B». Пока это цепочки и деревья, всё разрешается. Цикл (T1 → T2 → T1) означает вечное ожидание. Обнаружение deadlock - это поиск цикла.

Как находится

Строить граф на каждую блокировку дорого, а почти все ожидания разрешаются сами. Поэтому при постановке в очередь взводится таймер deadlock_timeout (по умолчанию 1 с). Если за это время блокировку не выдали - запускается детектор и ищет цикл. Нашёл - откатывает жертву; нет - ждёт дальше. Отсюда задержка между тупиком и его разрывом ≈ 1 с.

Сообщение

ERROR:  deadlock detected
DETAIL:  Process 412 waits for ShareLock on transaction 1033; blocked by process 410.
         Process 410 waits for ShareLock on transaction 1034; blocked by process 412.
CONTEXT:  while updating tuple (0,5) in relation "bookings"

SQLSTATE - 40P01. Жертва получает полный ROLLBACK (вся транзакция, не последний запрос), вторая продолжает. Счётчик pg_stat_database.deadlocks растёт на единицу.

Неочевидные источники

Двух явных UPDATE не нужно. Один UPDATE на несколько строк в разном порядке обхода даёт тот же цикл (порядок задаёт план, не порядок в IN). Перекрёстные вставки по внешнему ключу - тоже.

Как избежать

  • единый порядок блокировок (ORDER BY id в FOR UPDATE) делает граф ациклическим - цикл становится невозможен;
  • короткие транзакции сужают окно пересечения;
  • ретрай на 40P01: deadlock штатен, приложение обязано повторять.

В отличие от idle-in-transaction-cascade, deadlock разрывает сам сервер. За очередью блокировок стоит механизм из relation-locks и row-locks.

§ команды

bash
SELECT deadlocks FROM pg_stat_database WHERE datname = current_database();

Сколько взаимоблокировок случилось в базе

bash
SET deadlock_timeout = '1s';

Через сколько ждать перед запуском детектора циклов

bash
SELECT * FROM bookings WHERE book_ref IN ('000001','000002') ORDER BY book_ref FOR UPDATE;

Блокировать строки в едином порядке - профилактика deadlock

§ см. также

  • relation-locksТяжёлые блокировки отношенийКаждая команда берёт на таблицу блокировку одного из 8 режимов: от ACCESS SHARE (обычный SELECT) до ACCESS EXCLUSIVE (DROP/ALTER), который конфликтует со всеми. Блокировка держится до конца транзакции.
  • row-locksБлокировки строкБлокировка строки хранится в самой строке (xmax + infomask), а не в pg_locks. Режимов четыре: FOR KEY SHARE, FOR SHARE, FOR NO KEY UPDATE, FOR UPDATE. Слабые нужны, чтобы внешние ключи не сериализовали вставки.
  • idle-in-transaction-cascadeidle-in-transaction и каскад блокировокЗабытый открытый BEGIN держит блокировку до конца транзакции. Если за ним в честной FIFO-очереди встанет ALTER TABLE (ACCESS EXCLUSIVE), то даже совместимые SELECT за ним тоже повиснут - встаёт вся таблица.
Footer
linuxlab-
Copyright © 2026 LinuxLab. Все права защищены.
Учебники
Цены
О платформе
Конфиденциальность и куки