pgBouncerでPostgreSQLの接続プールを設定する手順|最大接続数の削減とpgbouncer.iniの書き方

宮崎智広 この記事の監修:宮崎智広(Linux実務・教育歴20年以上・受講者3,100名超)
HOME > Linux技術 リナックスマスター.JP(Linuxマスター.JP) > Linuxtips > データーベース管理 > pgBouncerでPostgreSQLの接続プールを設定する手順|最大接続数の削減とpgbouncer.iniの書き方
「アプリサーバーを増やすたびにPostgreSQLへの接続が増えて、『FATAL: sorry, too many clients already』が頻発する…」
こんな状況に直面したことはないでしょうか。PostgreSQLのmax_connectionsを単純に増やすと、コネクション1本あたり数MB~数十MBのメモリを消費するため、サーバーが詰まる問題は根本的に解決しません。

そこで登場するのがpgBouncerです。アプリとPostgreSQLの間に入って接続をプールし、PostgreSQL本体への接続数を大幅に削減します。アプリ側は数百コネクションを持てるのに、PostgreSQL実体への接続は数十本に抑えるという、LinuxサーバーのDB運用では定番の構成です。

この記事では、pgBouncerのインストールからpgbouncer.iniの設定・動作確認・監視まで、Rocky Linux 9.4 / Ubuntu 24.04 LTSで動作確認した手順を解説します。

この記事のポイント

・pgBouncerをアプリとPostgreSQLの間に挟むことで、PostgreSQL本体の同時接続数を削減できる
・pgbouncer.iniの[databases]と[pgbouncer]セクションを設定し、userlist.txtでパスワードを登録する
・pool_modeはtransactionが最も効率的だが、prepared statementの扱いに注意が必要
・SHOW STATSとSHOW POOLSでリアルタイムに接続状況を監視できる


「このままじゃマズい」と感じていませんか?
参考書を開く気力もない、同年代に取り残される不安——
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

pgBouncerとは何か — PostgreSQLの接続数問題を解消するコネクションプーラー

PostgreSQLは接続ごとにプロセスを生成する(プロセスモデル)アーキテクチャです。この設計は安定性と分離性に優れる一方、同時接続数が多いと以下の問題が発生します。

・メモリ消費:コネクション1本あたり最低5~10MBのメモリを消費する。100接続で500MB以上が接続維持だけで消える
・プロセス起動コスト:短命なコネクションを大量に張ると、forkcのオーバーヘッドが無視できなくなる
・max_connectionsの上限:デフォルト100。増やせるが、リソース消費との兼ね合いで無制限には増やせない

pgBouncerはアプリとPostgreSQLの間に立つプロキシで、アプリからの接続をプールして再利用します。アプリ側は「1リクエスト1コネクション」のように見えても、pgBouncer側でPostgreSQLへのコネクションを使い回すため、PostgreSQL本体への接続数を劇的に減らせます。

比較項目 pgBouncerなし pgBouncerあり
アプリ→DB接続数 アプリスレッド数分(例: 200) pool_size設定値(例: 20)
PostgreSQLメモリ消費 大(接続数×5~10MB) 小(プール数×5~10MB)
コネクション確立コスト 毎リクエスト発生 初回プール確立のみ
設定の複雑さ 不要 pgbouncer.ini + userlist.txtが必要

pgBouncerをLinuxサーバーへインストールする

1. Rocky Linux / RHEL 9 でのインストール

Rocky Linux 9ではAppStreamリポジトリにpgBouncerが含まれています。

# パッケージを確認 dnf list pgbouncer # インストール sudo dnf install -y pgbouncer # バージョン確認 pgbouncer --version

実行結果の例:

PgBouncer 1.22.0

PostgreSQL公式リポジトリ(PGDG)から新しいバージョンを使う場合は、`pgdg-redhat-repo`を追加したうえで`dnf install pgbouncer`を実行します。

2. Ubuntu 24.04 LTS でのインストール

sudo apt update sudo apt install -y pgbouncer pgbouncer --version

3. 設定ファイルの場所を確認する

# Rocky Linux / RHEL ls /etc/pgbouncer/ # Ubuntu ls /etc/pgbouncer/

いずれも `/etc/pgbouncer/pgbouncer.ini` と `/etc/pgbouncer/userlist.txt` が配置されています。

pgbouncer.iniの基本設定 — [databases]と[pgbouncer]セクションの書き方

pgBouncer の設定ファイルは大きく2セクションに分かれます。

1. [databases]セクション — 接続先DBを定義する

[databases] # エイリアス名 = host=接続先 port=ポート dbname=DB名 myapp = host=127.0.0.1 port=5432 dbname=myapp_db # 全DB名でそのまま受け付ける場合(ワイルドカード) # * = host=127.0.0.1 port=5432

`myapp`は外部から接続するときのDB名エイリアスです。アプリ側は`psql -h 127.0.0.1 -p 6432 -d myapp`と接続し、pgBouncerが`127.0.0.1:5432/myapp_db`へ転送します。

2. [pgbouncer]セクション — リスニングと接続数を設定する

[pgbouncer] # pgBouncerがリッスンするアドレスとポート listen_addr = 127.0.0.1 listen_port = 6432 # 認証方式(scram-sha-256 または md5) auth_type = scram-sha-256 auth_file = /etc/pgbouncer/userlist.txt # プールモード(後述) pool_mode = transaction # DB単位の最大コネクション数(PostgreSQL側の接続数上限) max_client_conn = 200 default_pool_size = 20 # ログ設定 logfile = /var/log/pgbouncer/pgbouncer.log pidfile = /var/run/pgbouncer/pgbouncer.pid # 管理DB(SHOW STATS等で使用) admin_users = pgbouncer_admin stats_users = pgbouncer_stats

重要なパラメータの意味:

・max_client_conn:pgBouncerがアプリ側から受け付ける最大接続数。PostgreSQLのmax_connectionsより大きくてよい
・default_pool_size:pgBouncerがPostgreSQL側に維持するコネクション数。PostgreSQLの実接続数がこの数値に制限される
・listen_port:6432がpgBouncer、5432がPostgreSQL本体。アプリは6432に向ける

userlist.txtでパスワード認証を設定する

pgBouncerはPostgreSQLへの接続時に自分が代わりに認証を行います。userlist.txtに接続に使うユーザー名とパスワードのハッシュを登録します。

1. PostgreSQLでパスワードハッシュを取得する

# PostgreSQLに接続 sudo -u postgres psql # pgBouncerが使う接続ユーザーのハッシュを確認 SELECT usename, passwd FROM pg_shadow WHERE usename = 'myapp_user';

出力例:

usename | passwd ------------+------------------------------------------------------------------------ myapp_user | SCRAM-SHA-256$4096:xxxxxxxxxxxxxxxx==$yyy...==:zzz...== (1 row)

2. userlist.txtに登録する

# /etc/pgbouncer/userlist.txt の形式 # "ユーザー名" "パスワードハッシュ" "myapp_user" "SCRAM-SHA-256$4096:xxxxxxxxxxxxxxxx==$yyy...==:zzz...==" "pgbouncer_admin" "md5xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

注意:auth_type = scram-sha-256 を使う場合、userlist.txtにはpg_shadowから取得したSCRAM-SHA-256形式のハッシュをそのまま貼り付けます。平文パスワードを書いてはいけません。

プールモード(session/transaction/statement)の選び方

pool_modeはpgBouncerの動作を決める最重要パラメータです。
pool_mode コネクション解放タイミング 特徴・注意点
session クライアントが切断したとき 最安全。prepared statementも問題なし。プール効率は低い
transaction トランザクション終了時(COMMIT/ROLLBACK) 最効率。prepared statementはSET session変数を使うと問題あり(後述)
statement SQLステートメント1文の終了時 トランザクションが使えない。特殊用途のみ
実務での推奨:Webアプリや短命なトランザクションが主体ならtransactionモードが最も効率的です。ただし、以下のパターンはtransactionモードで問題が出ます。

・プリペアドステートメント(PREPARE/EXECUTE):トランザクション間でサーバー側のprepared statementが保持されないためエラーになる。アプリ側でsimple query modeを使うか、sessionモードに切り替える
・SET文(SET search_path など):セッション変数がトランザクションをまたいで保持されないため、意図しない動作になる場合がある

Rails/Django/Laravel等のORMはデフォルトでprepared statementを使う設定のものが多いです。ORM側の設定で無効化するか、pgBouncer側でserver_reset_query = DISCARDを設定することで回避できます。
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、20年以上の運用経験を持つ現役エンジニアがpgBouncerの設定を含むPostgreSQLの実践スキルを教えます。 Linux Master Pro Seminar の詳細を見る >>

pgBouncerを起動して接続確認する

1. 設定ファイルの構文チェック

pgbouncer -d /etc/pgbouncer/pgbouncer.ini # エラーなしであれば設定ファイルは正常

2. systemctlで起動する

# 起動 sudo systemctl start pgbouncer # 自動起動を有効化 sudo systemctl enable pgbouncer # ステータス確認 sudo systemctl status pgbouncer

正常起動時の出力例:

* pgbouncer.service - A lightweight connection pooler for PostgreSQL Loaded: loaded (/usr/lib/systemd/system/pgbouncer.service; enabled; preset: disabled) Active: active (running) since Thu 2026-09-25 10:12:34 JST; 3s ago Main PID: 12345 (pgbouncer) Tasks: 2 (limit: 23156) Memory: 2.3 M CPU: 8ms CGroup: /system.slice/pgbouncer.service +--12345 pgbouncer /etc/pgbouncer/pgbouncer.ini

3. psqlでpgBouncer経由の接続を確認する

# pgBouncer経由でPostgreSQLへ接続(ポート6432を指定) psql -h 127.0.0.1 -p 6432 -U myapp_user -d myapp # 接続できたら実際にPostgreSQL本体に繋がっているか確認 myapp=> SELECT version();

実行結果:

version --------------------------------------------------------------------------------------------------------- PostgreSQL 16.3 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 11.4.1 20231218 (Red Hat 11.4.1-3), 64-bit (1 row)

SHOW STATSとSHOW POOLSで接続状況を監視する

pgBouncerは内部管理用の仮想データベース(pgbouncer)を持っており、接続状況をリアルタイムで確認できます。

1. 管理DBへ接続する

# admin_usersに設定したユーザーでpgbouncerDBへ接続 psql -h 127.0.0.1 -p 6432 -U pgbouncer_admin pgbouncer

2. SHOW POOLSで現在のプール状態を確認する

pgbouncer=# SHOW POOLS;

出力例:

database | user | cl_active | cl_waiting | sv_active | sv_idle | sv_used | sv_tested | sv_login | maxwait ------------+-----------+-----------+------------+-----------+---------+---------+-----------+----------+--------- myapp | myapp_user| 8 | 0 | 8 | 12 | 0 | 0 | 0 | 0 (1 row)

各列の意味:

・cl_active:pgBouncerに接続中のアクティブなクライアント数
・cl_waiting:プールが満杯でコネクション待ちのクライアント数(ここが増えると危険)
・sv_active:PostgreSQL側で使用中のコネクション数
・sv_idle:プール内の待機中コネクション数
・maxwait:最大待機秒数(増加したら`default_pool_size`を引き上げる目安)

3. SHOW STATSで累積統計を確認する

pgbouncer=# SHOW STATS;

出力例:

database | total_xact_count | total_query_count | total_received | total_sent | total_xact_time | total_query_time | avg_xact_time | avg_query_time ----------+------------------+-------------------+----------------+------------+-----------------+------------------+---------------+---------------- myapp | 2481 | 8935 | 29843291 | 87654321 | 3271845201 | 1248901234 | 1318 | 139 (1 row)

`avg_query_time`(マイクロ秒単位)が突然跳ね上がった場合は、PostgreSQL側でスロークエリが発生しているサインです。

よくある問題と対処法

エラー: prepared statement "..." does not exist

pool_mode = transactionのとき、アプリ側がprepared statementを使っていると発生します。

対処法1 — pgBouncerにDISCARD ALLを設定する:

# pgbouncer.iniの[pgbouncer]セクションに追加 server_reset_query = DISCARD ALL

対処法2 — アプリ側でprepared statementを無効化する(例: Rails):

# database.yml(Rails) production: prepared_statements: false

エラー: authentication failed for user

userlist.txtのパスワードハッシュ形式とauth_typeが一致していない場合に発生します。

・auth_type = scram-sha-256のとき: userlist.txtには`SCRAM-SHA-256$...`形式のハッシュを記載する
・auth_type = md5のとき: userlist.txtには`md5xxxxxxxx...`形式のmd5ハッシュを記載する

pg_shadowから取得したpasswd列の値をそのまま使うのが最も確実です。

設定変更を反映する(再起動不要)

pgbouncerはHUPシグナルで設定ファイルを再読み込みします。

# systemd経由でリロード sudo systemctl reload pgbouncer # または管理DBから psql -h 127.0.0.1 -p 6432 -U pgbouncer_admin pgbouncer -c "RELOAD;"

ログでエラーを確認する

# リアルタイムでログを追う sudo journalctl -u pgbouncer -f # またはログファイル直接 sudo tail -f /var/log/pgbouncer/pgbouncer.log

本記事のまとめ

やりたいこと 設定・コマンド
pgBouncerをインストールする(RHEL系) sudo dnf install pgbouncer
接続先DBを定義する pgbouncer.ini の [databases] セクション
アプリ側の最大接続数を設定する max_client_conn = 200
PostgreSQL側への実接続数を制限する default_pool_size = 20
最も効率的なプールモードを使う pool_mode = transaction
プールの状況をリアルタイム確認する SHOW POOLS;(管理DB経由)
設定を再起動なしで反映する sudo systemctl reload pgbouncer
pgBouncerを挟むことで、PostgreSQLへの実接続数を劇的に削減できます。max_connectionsの上限に悩んでいる場合は、まずpool_mode = transactionで運用してみてください。prepared statementの問題が出たときだけsessionモードに切り替えるか、アプリ側の設定を変更するという判断フローが実務では多いです。

PostgreSQLのチューニングや自前でのサーバー運用を体系的に学びたい方は、下記のセミナー情報もご覧ください。
現場で通用するLinuxサーバー管理・PostgreSQL運用のスキルを体系的に身につけたい方へ。20年以上の現役サーバー管理者が実機ハンズオンで実践的な構築・運用・チューニングの技術を教えます。
Linux Master Pro Seminar の詳細を見る >>

無料メルマガで学習を続ける

Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。

登録無料・いつでも解除できます

暗記不要・1時間後にはサーバーが動く

3,100名以上が実践した「型」を無料で公開中

プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。

姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

Linux無料マニュアル(図解60P) 名前とメールで30秒登録
宮崎 智広

この記事を書いた人

宮崎 智広(みやざき ともひろ)

株式会社イーネットマーキュリー代表。現役のLinuxサーバー管理者として20年以上の実務経験を持ち、これまでに累計3,100名以上のエンジニアを指導してきたLinux教育のプロフェッショナル。「現場で本当に使える技術」を体系的に伝えることをモットーに、実践型のLinuxセミナーの開催や無料マニュアルの配布を通じてLinux人材の育成に取り組んでいる。

趣味は、キャンプにカメラ、トラウト釣り。好きな食べ物は、ラーメンにお酒。休肝日が作れない、酒量を減らせないのが悩み。最近、ドラマ「フライトエンジェル」を観て涙腺が崩壊しました。