Взаимная блокировка двух транзакций
Ошибка deadlock detected, код 40P01, в логах Directum RX: PostgreSQL откатил одну из двух транзакций, которые ждали друг друга. Что включить в журнале и что передать разработчикам.
Что это значит
Две транзакции держат блокировки, нужные друг другу. PostgreSQL находит такой цикл и откатывает одну из них, чтобы вторая продолжила работу. Пользователь видит ошибку при сохранении, повтор обычно проходит. База при этом исправна: это её штатная защита.
Источник почти всегда в прикладной логике: два процесса меняют одни и те же записи в разном порядке. Например, пользователь сохраняет карточку, а фоновое задание в это время обновляет те же строки.
Как проверить
В логе PostgreSQL рядом с ошибкой есть строки DETAIL: Process 123 waits for ShareLock on transaction ...; blocked by process 456 и тексты обоих запросов. Если их нет, включите:
log_lock_waits = on
deadlock_timeout = 1s
Параметры применяются перечитыванием конфигурации, перезапуск не нужен.
Что сделать
- Собрать с одного случая: время, оба запроса из
DETAILиCONTEXT, какой сервис их выполнял. - Передать это вендору или вашим разработчикам. Лечится порядком обращения к записям в коде, настройкой базы это не исправить.
- Проверить, нет ли долгих транзакций: они увеличивают шанс цикла.
Подробный разбор с примерами: Дедлоки 40P01 в PostgreSQL под Directum RX.