За замовчуванням PostgreSQL чекає безкінечно: запит може виконуватися годинами, а очікування блокування - тривати вічно. Таймаути перетворюють «завис» на зрозумілу помилку.
statement_timeout- максимальний час виконання однієї команди. Після нього запит скасовується з помилкою.lock_timeout- максимальний час очікування блокування. Сам запит може йти довго, але чекати на чужі блокування - не довше вказаного.idle_in_transaction_session_timeout- розірвати сесію, що простоює всередині відкритої транзакції.transaction_timeout(PostgreSQL 17+) - ліміт на всю транзакцію.
Де налаштовувати - на різних рівнях:
-- для ролі застосунку
ALTER ROLE app_user SET statement_timeout = '30s';
ALTER ROLE app_user SET idle_in_transaction_session_timeout = '60s';
-- для окремої сесії чи транзакції
SET lock_timeout = '3s'; -- для сесії
SET LOCAL statement_timeout = '5min'; -- лише до кінця поточної транзакції
Типові значення:
- Веб-запити:
statement_timeoutкілька секунд - веб-запит, що чекає базу хвилину, однаково нікому не потрібен, а тримає з'єднання з пулу. - Міграції:
lock_timeout2-5 секунд, щобALTER TABLEне вишикував чергу з усіх запитів;statement_timeout- побільше або вимкнений для довгих операцій на зразокCREATE INDEX CONCURRENTLY. - Звіти й фонові задачі: окрема роль чи
SET LOCALз більшими лімітами.
Застереження:
- Глобальний
statement_timeoutуpostgresql.confзачепить і адміністративні операції -pg_dump, вакуум вручну. Краще налаштовувати на роль застосунку. - З PgBouncer у режимі transaction pooling
SETбезLOCAL«протікає» в інші сесії - використовуватиSET LOCALабо налаштування ролі. - Помилку таймауту застосунок має обробляти: логувати з текстом запиту й показувати користувачу зрозуміле повідомлення, а не 500.