コネクションプール
データベース接続を事前に確保してプールし、リクエストごとの接続コストを削減する仕組み
コネクションプールとは
コネクションプールは、データベースへの接続 (コネクション) を事前に複数確保しておき、リクエストが来たら空いている接続を貸し出し、処理が終わったらプールに返却する仕組みである。
データベース接続の確立には、TCP ハンドシェイク (3-way handshake)、TLS ネゴシエーション (暗号化接続の場合)、認証処理が必要で、通常 20〜100ms のオーバーヘッドが発生する。リクエストごとに接続を確立・切断すると、このオーバーヘッドが毎回加算される。コネクションプールはこれを初回のみに抑え、以降は確立済みの接続を再利用する。
コネクションプールの動作原理
アプリケーションが接続を要求すると、プールは確立済みの空き接続を貸し出す。クエリ実行後、接続は切断されずプールに返却され、次のリクエストで再利用される。これにより、接続確立のオーバーヘッドを初回のみに抑えられる。
アプリケーション コネクションプール データベース
│ │ │
├── 接続要求 ──────────────→ 空き接続を貸出 ─────→ (既存接続を再利用)
│ │ │
├── クエリ実行 ──────────────────────────────────→ 処理実行
│ │ │
├── 接続返却 ──────────────→ プールに戻す │
│ │ │
└── (接続は切断されない) └── (次のリクエストで再利用) │
プールサイズの設計
プールサイズの設定は、パフォーマンスに直結する重要な設計判断だ。
| パラメータ | 意味 | 典型的な値 |
|---|---|---|
| minPoolSize | 常時確保する最小接続数 | 5〜10 |
| maxPoolSize | 最大接続数 | 20〜50 |
| idleTimeout | 未使用接続を閉じるまでの時間 | 30〜300 秒 |
| connectionTimeout | 接続取得の待機上限 | 5〜30 秒 |
パラメータ名はライブラリごとに違う。HikariCP では minimumIdle / maximumPoolSize / idleTimeout / connectionTimeout がこれに対応する。
プールサイズの算出式
PostgreSQL プロジェクトが出発点として示している経験則があり、Java のコネクションプール HikariCP の解説資料もこれを引いて紹介している。
最適なプールサイズ ≈ (CPU コア数 × 2) + ディスクスピンドル数
4 コアでディスク 1 本のサーバーなら 9、丸めて 10 程度が出発点になる。ここでのコア数はハイパースレッドを含めず、有効スピンドル数はアクティブなデータセットが完全にキャッシュに載っていれば 0 と数える (キャッシュヒット率が下がるほど実際のディスク本数に近づく)。式が示すのは同時に処理を進めている接続の数であり、待ちが多いワークロードではこれより大きい方が伸びる場合もあるため、最終的には実測で調整する。
プールサイズが大きすぎる場合の問題
直感に反するが、プールサイズを大きくしすぎるとパフォーマンスが低下する。データベース側で大量の接続を維持するメモリコストが増加し、コンテキストスイッチのオーバーヘッドも増える。PostgreSQL は 1 接続に 1 つのバックエンドプロセスを割り当てるプロセスモデルで、接続ごとに数 MB のメモリを使う。加えてソートやハッシュ結合ではクエリ内の演算ごとに work_mem 分の作業メモリを確保するため、同時接続が増えるほど使用量は跳ねやすい。max_connections を上げること自体も、それに比例した共有メモリの割り当てを招く。
Lambda とコネクションプールの問題
Lambda は同時実行数に応じてインスタンスが増えるため、各インスタンスがデータベース接続を確保すると、接続数が爆発的に増加する。
通常のサーバー: 1 プロセス × プールサイズ 20 = 20 接続
Lambda: 1000 同時実行 × 1 接続/インスタンス = 1000 接続
RDS の最大接続数は、パラメータグループの既定値がインスタンスの割当メモリ DBInstanceClassMemory から算出されるため、インスタンスサイズに依存する。算出式はエンジンごとに異なり、MySQL は DBInstanceClassMemory/12582880 (実質メモリ MB ÷ 12)、PostgreSQL は LEAST(DBInstanceClassMemory/9531392, 5000) (実質メモリ MB ÷ 9.5・上限 5,000) である。
| インスタンス | メモリ | 既定の最大接続数 (式からの目安) |
|---|---|---|
| db.t3.micro | 1 GiB | MySQL 約 85 / PostgreSQL 約 110 |
| db.t3.medium | 4 GiB | MySQL 約 340 / PostgreSQL 約 430 |
| db.r6g.large | 16 GiB | MySQL 約 1,360 / PostgreSQL 約 1,720 |
DBInstanceClassMemory はインスタンスクラスの公称メモリからマネージド用途の取り分を引いた値なので、実際の既定値は上の目安よりやや小さい。パラメータグループで引き上げられるが、その分メモリを消費する。
Lambda の同時実行数がこれを超えると、too many connections エラーが発生する。
解決策の比較
解決策の比較を以下に示す。
| 解決策 | 仕組み | コスト | 適するケース |
|---|---|---|---|
| RDS Proxy | AWS マネージドの接続プール | DB の vCPU 時間課金 (最低 2 vCPU 分) | RDS を使い続ける場合 |
| PgBouncer | OSS の接続プーラー (EC2 上) | EC2 費用 | 細かい制御が必要な場合 |
| DynamoDB | HTTP API、接続不要 | 従量課金 | サーバーレスネイティブ設計 |
RDS Proxy
RDS Proxy は Lambda とデータベースの間に入り、コネクションプールを一元管理する。Lambda の同時実行数が 1,000 でも、RDS Proxy がデータベースへの接続を数十本に集約する。
Lambda (1000 同時実行) → RDS Proxy (接続プール) → RDS (50 接続)
アプリケーションからプロキシへの接続は IAM 認証を強制でき、プロキシからデータベースへの認証は Secrets Manager に保存した資格情報 (または IAM データベース認証) を使う。データベースのパスワードを Lambda の環境変数に持たせる必要がなくなる。
DynamoDB なら不要
DynamoDB は HTTP ベースの API でアクセスするため、コネクションプールの問題が根本的に発生しない。サーバーレスアーキテクチャでは DynamoDB を選択する大きな理由の 1 つだ。
よくある落とし穴
- 接続リーク: 接続を取得した後、例外発生時に返却し忘れるとプールが枯渇する。
try-finallyやusingパターンで確実に返却する - アイドル接続の切断: データベースやネットワーク機器がアイドル接続を切断すると、プール内の接続が無効になる。接続取得時のバリデーション (
testOnBorrow) やキープアライブクエリで対策する - Lambda のコールドスタートとの相互作用: Lambda のコールドスタート時にコネクションプールが初期化され、接続確立のレイテンシが加算される。Provisioned Concurrency で緩和できる
「High Performance MySQL」(Baron Schwartz ら著) でコネクションプールの設計が詳しく解説されている。
詳しくは関連書籍を参照。
この記事は役に立ちましたか?
関連用語
コールドスタート
Lambda の初回呼び出し時に実行環境の初期化が発生し、レイテンシが増加する現象
サーバーレス
サーバーの管理をクラウドプロバイダーに委ね、コードの実行に対してのみ課金されるコンピューティングモデル
データベースインデックス
検索クエリの高速化のためにデータベースが維持する補助的なデータ構造
TCP 輻輳制御
ネットワークの混雑を検知し、送信速度を動的に調整して公平で効率的なデータ転送を実現する TCP の仕組み
オブジェクトプールパターン
生成コストの高いオブジェクトを事前に確保してプールし、再利用することでパフォーマンスを向上させるパターン
TCP 3-way ハンドシェイク
TCP 接続を確立するための 3 段階の手順で、SYN → SYN-ACK → ACK の順で行われる
関連する記事
データベース本ガイド - SQL から設計まで学べる技術書の選び方
データベースの基礎から設計、パフォーマンスチューニングまで学べる技術書の選び方と学習順序を紹介します。
障害対応の夜に思い出す、あの本の 1 ページ
本番障害の緊迫した場面で、過去に読んだ技術書の知識が助けてくれた経験はありませんか。「いつか役立つ」知識が「今この瞬間」に変わる読書の価値を考えます。
Linux 本ガイド - コマンドライン / しくみ / 性能の 3 層で選ぶ技術書
Linux を学ぶ技術書の選び方を 3 層 (コマンドラインの操作 → カーネルのしくみ → 性能と運用) で整理。新しい Linux の教科書や [試して理解] Linux のしくみなどの定番書の使い分けと、学ぶ順番を解説します。