コネクションプーリングとは？なぜ要るのか？を Oracle Database で簡単に説明してみる。

社内で「コネクションプーリングって何ですか？なぜ要るんですか？」という素朴な疑問が発生したので、Oracle Database をモデルにして簡単に説明してみますやで。
彡(ﾟ)(ﾟ)

# 1. 前提知識1：Oracle Database のプロセス・アーキテクチャ

Oracle Database は UNIX/Linuxプラットフォーム の場合はマルチプロセスのアーキテクチャが採用されています。

> Oracle Databaseデータベース概要 19c
> 15 プロセス・アーキテクチャ
> https://docs.oracle.com/cd/F19136_01/cncpt/process-architecture.html#GUID-85D9852E-5BF1-4AC0-9E5A-49F0570DBD7A
> プロセス実行のアーキテクチャは、オペレーティング・システムによって決まります。
> たとえば、Windowsでは、Oracleバックグラウンド・プロセスはプロセス内の実行スレッドです。
> LinuxおよびUNIXにおけるOracleプロセスは、オペレーティング・システム・プロセスか、またはオペレーティング・システム・プロセス内部のスレッドです。

Oracle Database では DB接続時 にサーバープロセスが生成されます。そのサーバープロセスとクライアント(SQLを発行するアプリケーション)が SQL をやり取りをすることで、様々な処理が行われます。マルチプロセスのアーキテクチャは下記マニュアルの図が全体感を掴むのに良いです。

> Oracle Database データベース概要 19c - Oracle Databaseアーキテクチャ
> https://docs.oracle.com/cd/F19136_01/cncpt/introduction-to-oracle-database.html#GUID-CF765A7D-9429-4901-BF33-36E0B0220293
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110066/25a4be00-596e-9dc2-6d22-17825bd6c6d5.png)


# 2. 前提知識2: Oracle Database のリスナー経由での接続処理とその問題

Oracle Database では大半のケースでリスナーに接続要求をしてサーバープロセスを生成します。

> Oracle Databaseによるサーバー・プロセスの作成方法
> https://docs.oracle.com/cd/F19136_01/cncpt/process-architecture.html#GUID-13FE4098-61DF-4D76-882D-551A88E0EBB8
> 接続にBequeathが使用されないときは、データベースによって次のようにサーバー・プロセスが作成されます。
> 1. クライアント・アプリケーションがリスナーまたはブローカから新規の接続をリクエストします。
> 2. リスナーまたはブローカが新規のプロセスまたはスレッドの作成を開始します。
> 3. オペレーティング・システムが新規のプロセスまたはスレッドを作成します。
> 4. Oracle Databaseが各種のコンポーネントおよび通知を初期化します。
> 5. データベースが接続および接続固有コードを引き渡します。

この接続時の処理はとても負荷が高い処理 かつ リスナーでシリアライズ(順番待ち)されるため、秒間何千何万ものSQLを処理しようとするとこの接続時の処理がボトルネックになって性能(スループット/レスポンス)がスケールしにくくなります。これが直後のコネクションプーリングが必要とされる理由となります。

# 3. コネクションプーリングとは？

コネクションプーリングはアプリケーション側(クライアント側)で予め一定数のDB接続を確保しておいて、それをアプリケーションで使い廻す仕組みです。DB接続を予め実行して貯めて(プールして)おき、その接続をアプリケーションで共有して接続時の高負荷を回避します。下記リンクが解り易いでしょうか。

> コネクションプーリング
> https://e-words.jp/w/%E3%82%B3%E3%83%8D%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3%E3%83%97%E3%83%BC%E3%83%AA%E3%83%B3%E3%82%B0.html
> 外部のプログラムがデータベースの内容を読み書きする場合、DBMSへ処理を依頼するが、そのためにはデータを送受信するコネクション（connection）の確立を行う必要がある。接続や切断の処理を行うたびに一定の負荷が生じるため、頻繁にアクセスが行われるシステムではこのオーバーヘッドのために性能が劣化する場合がある。

コネクションプーリングの仕組みを自分で実装する事も可能ですが、例えば Java でアプリケーションサーバー(Oracle WebLogic Server や Tomcat, IBM WebSphereなど)を採用する場合は、アプリケーションサーバー側でコネクションプーリングの仕組みが実装されているため、その仕組みを利用する事が多いはずです。
下記は WebLogic のコネクションプーリングの仕組みである、JDBCデータ・ソースのマニュアルです。

> Oracle WebLogic Server JDBCデータ・ソースの管理
> 4 JDBCデータ・ソース・タイプ
> https://docs.oracle.com/cd/G29095_01/fusion-middleware/weblogic-server/14.1.2/jdbca/jdbc-data-sources-types.html

近年はコンテナ技術の台頭でアプリケーション側でコネクションを保持しておく事が難しいケースもあります。コンテナはコンテナ自身の生成や破棄を繰り返すのが前提になり、コンテナ破棄のタイミングでDB接続も失われるからです。OCI FunctionsやAWS Lambdaの様なサーバーレス処理でも同様の問題が発生し得ます。また採用する言語やフレームワークによってはコネクションプーリングの仕組みが無い場合もあります。
そのようなケースではデータストア側でコネクションプーリングと同等の仕組みが提供される場合もあります。Oracle Database の場合は データベース常駐接続プーリング(DRCP)、クラウドだと AWS の RDS Proxy がデータストア側のコネクションプーリングに相当します。

> データベース常駐接続プーリング(DRCP)
> https://docs.oracle.com/cd/F19136_01/cncpt/application-and-networking-architecture.html#GUID-531EEE8A-B00A-4C03-A2ED-D45D92B3F797
> 
> Autonomous Databaseでのデータベース常駐接続プーリング(DRCP)の使用
> https://docs.oracle.com/cd//E83857_01/paas/autonomous-database/adbsa/connect-drcp.html
> 
> Amazon RDS Proxy
> https://aws.amazon.com/jp/rds/proxy/

# 4. コネクションプーリングによって発生する問題と回避策

コネクションプーリングによって発生する問題として無効接続が挙げられます。サーバープロセス側で問題が発生(プロセスのクラッシュやインスタンスダウン等)すると、そのサーバープロセスにクライアント側から SQL を実行するとハングしてしまいます(無効接続)。
無効接続問題を回避するため、多くのアプリケーションサーバー(WebLogicなど)ではコネクションプーリングの健全性をチェックする仕組みを備えています。下記は WebLogic の該当機能のマニュアルとなります。

> データ・ソースの接続テスト・オプション
> https://docs.oracle.com/cd/G29095_01/fusion-middleware/weblogic-server/14.1.2/jdbca/ds_tuning.html#GUID-AF27F5F9-33B2-4D61-98C2-49DABDCA5106

Oracle Database の場合は FAN/FCF という仕組みを備えています。アプリケーションサーバー側(WebLogic等)にインスタンスダウン等のイベントを通知(FAN)して、アプリケーションサーバー側で無効になった接続を破棄して再接続(FCF)します。データストア側からのイベント通知で動作するため、ポーリング型のSQL定期実行よりも問題を回避し易くなり可用性が向上します。

> Oracle Database 機能概要(P.199, 高速アプリケーション通知, Fast Application Notification: FAN)
> https://speakerdeck.com/oracle4engineer/oracle-database-ji-neng-gai-yao?slide=199

# 5. まとめ

コネクションプーリングを使用するとDB/データストア接続時の高負荷を回避できます。
皆さん上手くコネクションプーリングを活用しましょうね。
彡(^)(^)

# Appendix1. Oracle WebLogic Server のコネクションプーリング(JDBCデータソース)について

Oracle社製の Javaアプリケーションサーバーである WebLogic では様々な種類のコネクションプーリング(JDBCデータソース)が有ります。
それらのデータソースについてざっくりと解説彡(ﾟ)(ﾟ)

---

> デフォルト・データ・ソースの使用
> https://docs.oracle.com/cd/G29095_01/fusion-middleware/weblogic-server/14.1.2/jdbca/jdbc-data-sources-types.html#GUID-EE3DAF88-3D79-4271-803E-A288ECEE211D

デフォルト・データソースは WebLogic に組み込まれた Derbyデータベースへの接続を提供する事前定義済みデータソースとなります。Jakarta EE 8 に準拠したランタイムで動作する JDBC のコネクションプーリングとなります。JDBCコネクションプーリングの標準的な機能を提供します。

---

> 汎用データ・ソースの使用
> https://docs.oracle.com/cd/G29095_01/fusion-middleware/weblogic-server/14.1.2/jdbca/jdbc-data-sources-types.html#GUID-5F9CCFFC-6279-4D0B-8247-18BED441E3BD

汎用データ・ソースは Oracle Database など各種データストアへの接続を提供します。デフォルト・データ・ソース同様に Jakarta EE 8準拠のランタイムに対応した JDBC のコネクション・プーリングとなります。

---

> JDBCマルチ・データ・ソースの使用
> https://docs.oracle.com/cd/G29095_01/fusion-middleware/weblogic-server/14.1.2/jdbca/jdbc-data-sources-types.html#GUID-CF34E3FE-C329-4006-9506-34544B8447CD

JDBCマルチ・データソースは複数の汎用データソースをグループ化/抽象化したものとなります。その特性から事実上Oracle RAC専用？ということになるでしょうか。

Oracle RAC の DBノード(インスタンス) と 1vs1 で対応する汎用データソースをDBノード数分作成しておいて、マルチデータソースでそれらの汎用データソースをグループ化します。Oracle RAC のDBノードやインスタンスで障害が発生するとそのDBノード(インスタンス)に対応する汎用データソースは無効化されて、SQL実行は他の汎用データソース(DBノード)にバランシングされます。

マルチデータソースを利用するアプリケーション側からはDB障害は隠蔽されて、結果として可用性が向上します。

---

> Active GridLinkデータ・ソースの使用方法
> https://docs.oracle.com/cd/G29095_01/fusion-middleware/weblogic-server/14.1.2/jdbca/jdbc-data-sources-types.html#GUID-82D615E4-857E-4DC1-89D2-34270809690A

Active GridLink は前述の FAN(高速アプリケーション通知)/FCF(Fast Connection Failover) や RCLB(ランタイム接続ロード・バランス)、後述の Application Continuity(アプリケーション・コンティニュイティ)など Oracle RAC や Active Data Guard と高度に連携する機能を備えた JDBCデータソースとなり、主に高可用性にメリットが有ります。利用には WebLogic Suite のライセンスが必要です。

---

> ユニバーサル接続プール(UCP)・データ・ソースの使用
> https://docs.oracle.com/cd/G29095_01/fusion-middleware/weblogic-server/14.1.2/jdbca/jdbc-data-sources-types.html#GUID-91994E4A-5B7B-42A1-9584-9E1AB579FD40
> 
> Universal Connection Pool開発者ガイド
> https://docs.oracle.com/cd/F19136_01/jjucp/index.html

UCPデータソースは Oracle が (WebLogicとは独立して)提供する UCP(Universal Connection Pool) の機能を利用可能なデータソースとなります。前述の Active GridLinkよりも制限は多いですが FAN/FCF や下記の Application Continuity を使用でき、可用性が向上します。

> アプリケーション・コンティニュイティ対応クライアント
> https://speakerdeck.com/oracle4engineer/apurikesiyonkonteiniyuitei?slide=33

# Appendix2. アプリケーション・コンティニュイティ(Application Continuity)について

アプリケーション・コンティニュイティ(Application Continuity) は Oracle Database のエラー発生時に実行中のトランザクションをエラー時点から再実行する機能となります。トランザクションの再実行でエラーがクライアント側から隠蔽され、結果として可用性が向上します。

> アプリケーション・コンティニュイティ
> https://speakerdeck.com/oracle4engineer/apurikesiyonkonteiniyuitei
> 
> アプリケーション・コンティニュイティについて
> https://docs.oracle.com/cd/F19136_01/racad/ensuring-application-continuity.html#GUID-BD699AEB-9F85-42A8-8687-5A979918938D
> 
> Application Continuity を Java の UCP(ucp.jar) と Autonomous Database の ATP で試してみる。(Oracle Cloud Infrastructure)
> https://qiita.com/ora_gonsuke777/items/5e348a4f444b2d3643d0

コネクションプーリングとは独立した機能なので Appendix としていますが、FAN/FCF等と併用することで可用性向上が可能です。