LASSIC Media らしくメディア
PgBouncerでDB接続プールを外注導入
LASSIC IT事業部|元請(プライムベンダー)としてシステム保守・運用を受託
この記事のポイント
- PgBouncerがPostgreSQLの接続コストをどう吸収するのか、公式ドキュメントの定義に沿って整理します。
- session・transaction・statementの3つのプーリングモードの違いと、機能面の制約を比較します。
- max_client_connやdefault_pool_sizeなど主要パラメータと、外注・内製の判断軸を解説します。
目次
PgBouncerとコネクションプーリングの役割
PgBouncerとは、PostgreSQL用の軽量なコネクションプーラー(接続をプールし再利用するミドルウェア)であり、クライアントとPostgreSQLサーバーの間に立って接続を中継・再利用する仕組みを指します*1。アプリケーションが新規接続を要求するたびにPostgreSQLへ直接接続すると、接続数の増加に伴いサーバー側のメモリとCPUの消費が増えます*4。
PgBouncerを挟むことで、クライアント側の接続要求とPostgreSQL側の実接続数を分離できます。少数のサーバー接続を複数のクライアントで使い回すため、接続確立の頻度そのものを抑える設計です。
接続確立コストとPostgreSQLのmax_connections
PostgreSQLのmax_connectionsパラメータは、データベースサーバーへの同時接続の上限数を決めるパラメータであり、典型的な既定値は100接続です*2。PostgreSQLはこの値をもとに共有メモリなどのリソースサイズを確保するため、値を大きくするほどメモリ消費も増えます*2。
接続1本ごとにサーバー側でバックエンドプロセスが起動し、メモリとCPUを消費します*4。アプリケーションのインスタンス数やリクエスト量が増えるほど、この積み重ねが無視できなくなります。max_connectionsは起動時のみ設定できるパラメータであるため、稼働中に接続数上限を動的に変えることはできません*2。ここに、恒常的な接続過多を防ぐプーリングの意義があります。
session・transaction・statement — 3つのプーリングモード
PgBouncerのpool_modeパラメータは、サーバー接続を他のクライアントがいつ再利用できるかを指定する設定であり、既定値はsessionです*3。session・transaction・statementの3種類から選べます*3。
session poolingは「最も丁寧な方式」とされ、クライアントが接続している間はサーバー接続を専有し続けます*1。全PostgreSQL機能に対応できる一方、接続の再利用効率はもっとも低い方式です。
transaction poolingは、トランザクションの間だけサーバー接続をクライアントに割り当てる方式です*1。トランザクションが終わるとただちに接続がプールへ返却されるため、少数の実接続で多数のクライアントを回せます。ただし後述するとおり、セッション単位の機能の一部が使えなくなります。
statement pooling(ステートメントプーリング)は「もっとも積極的な方式」で、1クエリが終わるたびに接続をプールへ戻します*1。この方式ではマルチステートメントのトランザクションが許可されません*1。多重化の効率は高い一方、対応できるアプリケーションの作りはかなり限定されます。
| モード | 接続を返すタイミング | 機能面の制約 |
|---|---|---|
| session(既定値) | クライアントが切断したとき*1 | 制約なし。全PostgreSQL機能に対応*1 |
| transaction | トランザクション終了時*1 | SET/RESET・LISTEN・セッション単位のアドバイザリロックなどが使えません*5 |
| statement | クエリ終了時*1 | マルチステートメントトランザクションが禁止されます*1。transactionモードの制約も引き継ぎます |
max_client_conn・default_pool_sizeなど主要パラメータ
PgBouncerの設定は多岐にわたりますが、接続枯渇対策として最初に押さえるべきパラメータは限られます。max_client_connは、PgBouncerが受け付けるクライアント接続の上限数を指定するパラメータで、既定値は100です*3。この値はPostgreSQL側のmax_connectionsとは独立しており、クライアント側の受け口を広げるための設定です。
default_pool_sizeは、ユーザーとデータベースの組み合わせごとにPgBouncerが保持するサーバー接続数の上限を指定するパラメータで、既定値は20です*3。多数のクライアント接続をこの少数の実接続に収束させることが、プーリングの核心にあたります。
その他にも、プールの下限を維持するmin_pool_size(既定値0、無効)や、突発的な負荷に備える予備接続数を指定するreserve_pool_size(既定値0、無効)、アイドル状態のサーバー接続を閉じるまでの秒数を指定するserver_idle_timeout(既定値600秒)などがあります*3。自社のワークロード(アクセスパターンやデータベース構成)に合わせてこれらを調整するには、PostgreSQLとPgBouncer双方の挙動を理解した設計が欠かせません。
サーバーレス・Lambdaが引き起こす接続枯渇とPgBouncerの位置づけ
AWS Lambda(サーバーレスの実行環境)は数万規模の同時実行にスケールできますが、リレーショナルデータベースは同じ規模の同時接続を受け止める設計にはなっていません*4。トラフィックが増えるとLambdaが次々にインスタンスを増やし、各インスタンスが個別に接続を確立しようとするため、データベース側の接続上限に達しやすくなります*4。
この課題への対応として、AWSはRDS Proxyというマネージド型の接続プーリングサービスを提供しています*4。RDS ProxyはLambda関数が既存の接続を再利用できるようにし、データベースインスタンス側の接続管理にかかるメモリとCPUの消費を抑える仕組みです*4。PgBouncerは、この位置づけを自前のミドルウェアとして担う選択肢です。マネージドサービスを使わずコネクションプーリングを構成したい場合や、サーバーレス以外の実行環境も含めて一元的にプールを管理したい場合に検討されます。
PgBouncerを自前で運用するには、サービスの起動・監視・スケーリング・フェイルオーバーを自社で管理する必要があります*4。設定パラメータの妥当性検証や障害時の切り替え設計まで含めると、内製だけで完結させるにはミドルウェア運用の専門知識と継続的な保守体制が要ります。
prepared statementなどモード別の機能制約
PgBouncerは、プロトコルレベルのprepared plan(クライアントドライバが内部的に発行する準備済み実行計画)については、session・transaction・statementのいずれのモードでも対応しています*5。一方、SQL文として明示的に発行するPREPARE文とDEALLOCATE文は、sessionモードでのみ動作します*5。
transactionモードでprepared statementを扱うには、max_prepared_statementsパラメータを0以外の値に設定する必要があります*5。この設定を見落とすと、アプリケーション側でエラーが発生してから問題に気づく事態になりかねません。
ほかにも、transactionモードでは動作しない機能があります。セッション状態を変更するSET文・RESET文、非同期通知のLISTEN、トランザクション境界を超えて保持するWITH HOLDカーソル、行の保持設定を伴う一時テーブル、LOAD文、セッション単位のアドバイザリロックが該当します*5。これらの機能をアプリケーションが使っている場合、transaction・statementモードへ切り替える前に依存箇所を洗い出す作業が必要です。
外注と内製、どちらでPgBouncerを導入するか
PgBouncerとは、PostgreSQL用の軽量なコネクションプーラーであり、導入自体は設定ファイル1本で完結する軽さが特徴です。しかし、実運用に落とし込む工程は単純ではありません。アプリケーションが発行するSQLの棚卸し、pool_modeの選定、max_client_connやdefault_pool_sizeの妥当な値の見極め、そして障害時の切り替え設計まで、複数の専門領域が絡み合います。
内製で導入を進める場合、PostgreSQLの接続管理とPgBouncerの設定項目の両方に習熟した担当者が必要です。加えて、transactionモードへ移行する際にはアプリケーションコードの互換性検証が伴うため、開発チームとインフラ担当の連携も欠かせません。この検証を誤ると、PREPARE文を使う機能が本番環境で突然動かなくなるといった不具合につながります。
外部パートナーに依頼する場合は、既存のPostgreSQL構成とアプリケーションの接続パターンを診断した上で、モード選定とパラメータ設計、移行後の監視体制までを一括して任せられる点が違いになります。自社に運用担当者を新たに置かずに、設計・導入・保守までを外部の体制でカバーできることが実務上のメリットです。判断軸としては、社内にPostgreSQLとミドルウェア運用の双方に対応できる人員がいるかどうか、そして移行に伴うアプリケーション側の検証工数を確保できるかどうかが目安になります。
まとめ:PgBouncer導入で押さえる3つの判断軸
本稿では、PgBouncerによるPostgreSQLのコネクションプーリングについて、プーリングモードの違いと主要パラメータ、接続枯渇対策としての位置づけを整理しました。要点を3つに集約すると、第一にpool_modeはsession・transaction・statementの特性と機能制約を理解した上で選ぶ必要があります。第二にmax_client_connとdefault_pool_sizeは、クライアント側とサーバー側の接続数を別々に制御する設定であり、両方の妥当な値を見極めることが欠かせません。第三に、サーバーレス環境での接続枯渇対策としてPgBouncerを導入する場合は、アプリケーションの互換性検証と運用体制の確保が導入成否を分けます。
よくある質問
PgBouncerとRDS Proxyはどちらを選ぶべきですか。
両者は役割が近く、単純な優劣では決まりません。RDS Proxyはマネージドサービスとして提供され、サービス自体の運用をAWSに委ねられます*4。PgBouncerはOSS(オープンソースソフトウェア)として自前で構成するため、パラメータ設計の自由度は高い一方、起動・監視・フェイルオーバーの運用を自社または外部パートナーが担う必要があります*4。既存のインフラ構成やマネージドサービスの利用方針によって選択が変わります。
pool_modeはtransactionにしておけば問題ありませんか。
アプリケーションが使う機能によっては問題が生じます。transactionモードではSET/RESET・LISTEN・セッション単位のアドバイザリロックなどのセッション依存機能が動作しません*5。PREPARE文・DEALLOCATE文もsessionモードのみの対応です*5。移行前にアプリケーションが発行するSQLの棚卸しが必要です。
max_client_connとdefault_pool_sizeはどちらを先に決めるべきですか。
両者は別の階層を制御する設定のため、順序よりも関係性の理解が重要です。max_client_connはPgBouncerが受け付けるクライアント接続数の上限で既定値100、default_pool_sizeはユーザーとデータベースの組み合わせごとのサーバー接続数の上限で既定値20です*3。クライアント側の想定接続数とPostgreSQL側のmax_connectionsの両方を把握したうえで、両パラメータの値を組み立てます。
PgBouncerの導入を外注する場合、どこまで任せられますか。
現状のPostgreSQL構成とアプリケーションの接続パターンの診断から、pool_modeの選定、パラメータ設計、導入後の監視体制の構築までを一括で依頼できます。特にtransactionモードへの移行を検討する場合は、アプリケーション側の互換性検証も含めて相談できる体制が実務上の目安になります。
statementモードはどのような場合に使いますか。
statementモードは、クエリが終わるたびに接続をプールへ返す最も積極的な方式で、マルチステートメントトランザクションが禁止されます*1。1クエリ単位で完結する読み取り中心のワークロードなど、トランザクションをまとめて発行しない使い方に限って検討する方式です。一般的なアプリケーションではtransactionモードの利用が先に検討されます。
著者:テレリモ総研編集部 鈴木 亮佑
ご不明な点はお問い合わせフォームからもご連絡いただけます。
- *1 出典:PgBouncer「Features」
- *2 出典:PostgreSQL「Connections and Authentication」
- *3 出典:PgBouncer「Configuration」
- *4 出典:Amazon Web Services「Using Amazon RDS Proxy with AWS Lambda」
- *5 出典:PgBouncer「Features」