PostgreSQL Error 40P01: deadlock_detected — поиск и устранение дедлоков
- Ошибка приложения:
ERROR: deadlock detected (SQLSTATE 40P01). Detail: Process ... waits for ExclusiveLock... - Автоматический откат одной из транзакций ядром СУБД.
- Задержки и таймауты пользователей при одновременной записи в общие регистры.
1. Включение расширенного логирования взаимоблокировок
Настройте параметры в postgresql.conf для детальной записи участников дедлока в журнал:
ALTER SYSTEM SET deadlock_timeout = '1s';
ALTER SYSTEM SET log_lock_waits = on;
ALTER SYSTEM SET log_line_prefix = '%m [%p] %q%u@%d ';
SELECT pg_reload_conf();2. Анализ графа дедлока в логе PostgreSQL
В логе появится блок с описанием участников:
ERROR: deadlock detected
DETAIL: Process 12345 waits for ShareLock on transaction 9876; blocked by process 54321.
Process 54321 waits for ExclusiveLock on tuple (42,15) of relation 16420; blocked by process 12345.3. Определение конфликтующей таблицы по OID relation
SELECT oid, relname, relnamespace::regnamespace
FROM pg_class
WHERE oid = 16420;4. Устранение причин дедлока на уровне архитектуры
- Единый порядок сортировки: Обеспечьте обновление строк в таблицах строго в одинаковом порядке (например, сортируя ID по возрастанию перед UPDATE).
- Явные блокировки строк: Используйте
SELECT ... FOR UPDATEперед внесением изменений. - Уменьшение размера транзакций: Не держите транзакции открытыми во время сетевых вызовов или пауз пользователя.
Частые вопросы (FAQ)
Как PostgreSQL определяет наличие взаимной блокировки (Deadlock)?
Фоновый поток детектора блокировок просыпается по истечении deadlock_timeout (по умолчанию 1 секунда), строит ориентированный граф ожидания процессов и при обнаружении цикла принудительно прерывает одну из транзакций.
Какую транзакцию PostgreSQL выбирает в качестве жертвы дедлока?
СУБД прерывает ту транзакцию, откат которой приведет к наименьшим вычислительным затратам и быстрее разорвет цикл взаимной блокировки.
Помогает ли увеличение deadlock_timeout устранить взаимоблокировки?
Нет! Увеличение параметра лишь заставит клиентов дольше висеть в заблокированном состоянии перед получением неизбежной ошибки.
Как бороться с дедлоками в 1С:Предприятие?
Переведите конфигурацию на режим 'Управляемые блокировки', исключите чтение данных внутри транзакции без необходимости и оптимизируйте порядок проведения движений по регистрам.