Postgres: statement_timeout はアプリ用ロールに ALTER ROLE で設定する
暴走したクエリ 1 本が接続とロックを握り続けるのを防ぐため、ALTER ROLE app SET statement_timeout = '5s' のようにアプリが接続するロールに上限を付ける。マイグレーションやバッチは別ロール(または SET で上書き)にして長く走れるようにする。
なぜロール単位か
postgresql.confで全体に付けると、マイグレーションやpg_dump、分析クエリまで切れてしまう。- アプリ側のコードで毎回
SETするのは漏れやすい(接続プールで別の接続に当たる、など)。
ロールに付けておけば、そのロールでログインした全セッションに自動で効く。
設定例
sql
-- Web アプリ用: 短く
ALTER ROLE app SET statement_timeout = '5s';
-- トランザクションを開けたまま放置された接続を切る
ALTER ROLE app SET idle_in_transaction_session_timeout = '30s';
-- ロック待ちで詰まらないように(任意)
ALTER ROLE app SET lock_timeout = '2s';
-- バッチ用ロールは長め、またはセッション内で上書き
ALTER ROLE batch SET statement_timeout = '10min';sql
-- 確認(新しい接続から)
SHOW statement_timeout;
-- ロールに付いている設定の一覧
SELECT rolname, rolconfig FROM pg_roles WHERE rolconfig IS NOT NULL;注意点
ALTER ROLE ... SETは新しいセッションから効く。接続プールは張り直しが必要。- 特定のクエリだけ長く走らせたいときは、トランザクション内で
SET LOCAL statement_timeout = '60s'とする(PgBouncer の transaction モードでも安全。Postgres: PgBouncer の transaction モードではセッション状態が別の接続に漏れる。SET LOCAL と xact 系ロックを使う 参照)。 - タイムアウトで切られたクエリは
canceling statement due to statement timeoutエラーになる。アプリ側で再試行するかどうか決めておく。
出典
- @amitsinha__07 · 2026-10-23
- PostgreSQL ドキュメント
statement_timeout: postgresql.org