Запрос не дождался блокировки за время lock_timeout
«ERROR: canceling statement due to lock timeout» (SQLSTATE 55P03) в PostgreSQL: запрос ждал блокировку дольше, чем разрешено параметром lock_timeout, и был отменён. Как найти, кто держал блокировку.
Что это значит
Параметр lock_timeout ограничивает, сколько запрос может ждать блокировку строки или таблицы. Если блокировку держит другая транзакция дольше, запрос отменяется с этой ошибкой. Это защитный механизм: лучше отказ, чем бесконечная очередь ожидающих.
Чаще всего блокировку держит долгая транзакция: массовое обновление, перестроение индекса, сессия, которая открыла транзакцию и висит в состоянии idle in transaction.
Как проверить
Кто кого блокирует прямо сейчас:
SELECT pid, pg_blocking_pids(pid) AS blocked_by, state, now() - xact_start AS xact_age, left(query, 80)
FROM pg_stat_activity WHERE cardinality(pg_blocking_pids(pid)) > 0;
Для разбора задним числом включите log_lock_waits = on: в журнале появятся записи still waiting for lock с номером блокирующего процесса.
Что сделать
- Найти и завершить долгую транзакцию, если она зависла:
SELECT pg_terminate_backend(<pid>);. - Тяжёлые операции (перестроение, массовые изменения) переносить в окно обслуживания.
- Ограничить висящие транзакции параметром
idle_in_transaction_session_timeout.
Ошибка повторяется?
Запустите Диагностика: за полминуты он покажет состояние базы, брокера, поиска и сервера. С отчётом разберём причину за 30 минут бесплатного созвона.
Написать