コネクションプーリングとは?
前提知識
アプリのコードからデータベースにアクセスする際、通常、次のような手順を踏む。
-
TCP接続の確立、アプリとデータベースとの接続を確立
アプリ(クライアント)は、データベース(サーバー)と通信するために、まず TCP接続(3-way ハンドシェイク) を確立する。接続に必要な情報(ホスト、ポート、ユーザー名、パスワード、データベース名など)を用いて、データベースクライアントを初期化し、接続を確立する。 -
トランザクションを開始する(必要な場合)
複数のクエリを一貫して処理したい場合や、途中で失敗した際に全体を取り消したい場合は、トランザクションを開始する。 -
SQLを実行する
データの取得(SELECT)、挿入(INSERT)、更新(UPDATE)、削除(DELETE)など、目的に応じたSQLを実行する。 -
トランザクションを終了する(コミットまたはロールバック)
すべてのSQLが正常に完了すればコミットし、処理を確定させる。途中でエラーが発生した場合はロールバックし、変更を取り消す。 -
データベースとの接続を切断する
操作が完了したら、接続を明示的に閉じるか、接続プールを利用して再利用可能な状態に戻す。
コネクションプーリングについて
データベースとアプリケーションの接続(コネクション)を再利用する仕組みのこと。
新しい接続を毎回作成・破棄するのではなく、接続をあらかじめプール(Pool)に確保しておき、使い回すことで効率を上げる。
仕組み
-
プールの初期化(アプリ起動時)
アプリケーションが起動すると、コネクションプールライブラリがデータベースへの接続をあらかじめ一定数作成。 -
リクエストの発生 → 接続の取得
ユーザーからリクエストが来ると、アプリはプールから空いている接続を1つ借りてデータベース操作を行う。借りる → 使用中 → 一時的に専有状態 -
使用後 → 接続の返却
リクエストの処理が終わったら、アプリはその接続を 「切断せずに」プールへ返却 する。
この返却された接続は、次のリクエストで再利用される。 -
接続数が足りない場合(スケーリング)
プール内のすべての接続が使用中の場合、プールは必要に応じて一時的に接続を増やすことがある(設定による)。
それでも足りなければ、リクエストは待たされる(タイムアウト設定次第ではエラーになる)。 -
アイドル接続の管理
しばらく使われなかった接続は、自動的に閉じられることがある(アイドルタイムアウト)。
これは、リソース(DB側の接続上限)を無駄にしないためである。
メリット
-
パフォーマンス向上
毎回新しいDBコネクションを作成・破棄するオーバーヘッドを避けられるため、高速に処理できる。
特に多数の短時間のクエリを繰り返すWebアプリで効果大。 -
接続の再利用
コネクションを再利用することで、DBサーバーへの負荷を軽減。
アプリとDBの間でのTCPコネクション確立コストを削減。 -
スケーラビリティ
コネクションプールは「同時に使える最大接続数(=プールサイズ)」を制御できるので、複数ユーザーのリクエストに効率的に応答できる。プールサイズを調整することで、負荷に応じたチューニングが可能。 -
一貫した接続管理
コネクションプールは接続のタイムアウトや再接続、エラー処理などを集中管理できるため、安定した接続維持とトラブル対応が容易になる。また、同時に使える最大接続数(=プールサイズ)も制御できるため、過剰な接続によるDBの負荷を防げる。
デメリット
-
プール枯渇のリスク(接続不足)
アプリケーションが同時に大量の接続を必要とすると、プール内の接続数が足りなくなり、待ち状態やタイムアウトが発生する。特に、長時間コネクションを保持する処理(トランザクションなど)があると、他の処理が詰まりやすくなる。 -
コネクションリークの可能性
アプリ側で接続を 明示的に解放し忘れる(closeしない) と、プール内のコネクションが枯渇する。プールが満杯になると、新規リクエストが永遠に待機または失敗する。 -
DB側の接続上限に到達する危険
複数のアプリケーションインスタンスで大きなプールサイズを設定すると、DB側の同時接続数制限(例:PostgreSQL の max_connections)を超えるリスクがある。結果として、DBが新しい接続を受け付けられず、サービス全体が不安定になる。
Discussion