できない.dev

PostgreSQL で「sorry, too many clients already」が出て接続できない

FATAL: sorry, too many clients already は同時接続数が max_connections に達したサイン。
接続リークを止めるかコネクションプーラを挟むのが本筋で、max_connections の引き上げは最後の手段。

#postgresql#max_connections#pgbouncer#pooling#connection

公開:

要約

FATAL: sorry, too many clients already は、同時接続数がサーバーの max_connections 上限に達して新規接続を受け付けられない状態。
多くは接続リークか、プーラ無しでの接続乱立が原因。
まず溜まった接続を調べてリークを止め、恒常的に多い場合は PgBouncer などのプーラを挟む。max_connections の引き上げは共有メモリを増やすため最後の手段。

よくある原因

  1. 上限到達: 既定の max_connections = 100 に対し、アプリのプールや並列ジョブの合計がそれを超えている。
  2. 接続リーク: 取得した接続を返していない、例外時に close し損ねているなどで未使用接続が居座る。
  3. 多インスタンス: サーバーレス関数やコンテナの水平スケールで、各インスタンスが独立に接続プールを持つと総数が膨らむ。
  4. プーラ不在: リクエストごとに新規接続して即切る設計だと、ピークで瞬間的に上限を超える。

現状確認

今どれだけ接続があるか、誰が握っているかを見る。

SELECT count(*) FROM pg_stat_activity;
SELECT datname, usename, state, count(*)
FROM pg_stat_activity
GROUP BY datname, usename, state
ORDER BY count DESC;

解決策

1. コネクションプーラを挟む

PgBouncer を前段に置き、アプリは少数の物理接続を共有する。
サーバーレスや高並列ではこれが定石。

2. アプリ側のプールを適正化する

物理接続は「max_connections ÷ インスタンス数」を超えない範囲に抑え、確実に解放する。

# 例: max_connections=100、4 インスタンスなら 1 インスタンス 20 程度に
pool size <= 20

3. 必要なら max_connections を上げる

postgresql.conf で引き上げる。max_connections は再起動が必要で、値に比例して共有メモリを確保する(Connections and Authentication)。

max_connections = 200

この記事は役立ちましたか?