PostgreSQL 'ERROR: canceling statement due to statement timeout' の修正方法

beginner🐘 PostgreSQL2026-07-08| PostgreSQL (全バージョン), Linux/Unix, Docker, AWS RDS, Azure Database for PostgreSQL

Error Message

ERROR: canceling statement due to statement timeout
#postgresql#タイムアウト#statement_timeout#パフォーマンス#クエリ

TL;DR - クイック解決策

データ移行や重いレポート作成など、長時間かかるクエリを一度だけ実行する必要がある場合は、メインのクエリを実行する前にSQLエディタで以下のコマンドを実行してください。

-- 現在のセッションのタイムアウトを無効化する
SET statement_timeout = 0;

-- または特定の期間(例:5分)に設定する
SET statement_timeout = '5min';

現在のタイムアウト設定を確認するには、以下を実行します。

SHOW statement_timeout;

このエラーが発生する理由

ERROR: canceling statement due to statement timeout は、PostgreSQL サーバーが単一の SQL ステートメントの実行時間に制限を設けているために発生します。クエリがこの制限を超えると、システムリソースを無制限に消費し続けるのを防ぐために、サーバーはそのプロセスを強制終了します。

この制限は statement_timeout パラメータによって制御されます。デフォルトは 0(タイムアウトなし)であることが多いですが、AWS RDS などのマネージドデータベースサービスや DBA(データベース管理者)は、データベースの応答性を維持するためにデフォルトの制限(例:30秒や60秒)を設定していることがあります。

エラーの修正方法

方法 1: 現在のセッションのタイムアウトを変更する

これは現在の接続にのみ影響するため、最も安全な方法です。単発のタスクに最適です。

-- このセッションのみタイムアウトを10分に設定
SET statement_timeout = '10min';

-- ここで重いクエリを実行
SELECT * FROM large_table JOIN another_large_table ...;

方法 2: 特定のユーザーまたはデータベースのタイムアウトを変更する

常に長時間のタスクを実行する特定のバックグラウンドワーカーユーザーがいる場合、アプリケーションの他の部分に影響を与えることなく、そのユーザーに対してのみ制限を増やすことができます。

-- 特定のユーザーに適用
ALTER ROLE reports_user SET statement_timeout = '1 hour';

-- 特定のデータベースに適用
ALTER DATABASE analytics_db SET statement_timeout = '30min';

方法 3: グローバル設定を変更する

サーバーへのすべての接続に対して制限を変更するには、postgresql.conf ファイルを修正します。これにはスーパーユーザー権限が必要であり、設定の再読み込みが必要になる場合があることに注意してください。

  • postgresql.conf ファイルを探します。
  • statement_timeout の行を見つけます。
  • 値を変更します(単位が指定されていない場合、値はミリ秒単位です)。
# グローバルタイムアウトを2分に設定
statement_timeout = 120000 

保存後、設定を再読み込みします:

SELECT pg_reload_conf();

方法 4: クエリを最適化する(長期的な解決策)

タイムアウトを増やすことは、多くの場合、一時しのぎに過ぎません。以前は高速だったクエリがタイムアウトするようになった場合は、EXPLAIN ANALYZE を使用して遅い理由を調査する必要があります。

EXPLAIN ANALYZE 
SELECT * FROM orders 
WHERE created_at > '2023-01-01' 
ORDER BY total_amount DESC;

大きなテーブルに対する Seq Scan (シーケンシャルスキャン) を探してください。不足しているインデックスを追加することが、通常、そもそもタイムアウトエラーを発生させないための最善の方法です。

確認方法

変更が反映されたことを確認するには、エラーが発生していたのと同じ環境で次のコマンドを実行します:

SHOW statement_timeout;

出力が 0 の場合、タイムアウトは無効になっています。5min のような値が表示される場合、それが新しい制限です。クエリを再実行してみてください。以前の時間制限を超えて処理が進むはずです。

参考文献

Related Error Notes