# データベース接続モデル WebアプリケーションサーバがRDBMSなどのデータベースサーバと接続を管理する方式の分類。接続コスト・リソース管理・ロードバランシング・フェイルオーバの各側面でトレードオフが生じる。 出典: [[@2015__yuuk.io__architecture-of-database-connection]]([[Yuuki Tsubouchi]]、2015年) ## 接続オーバヘッドの構造 RDBMSへの接続は複数層のオーバヘッドを持つ: 1. **TCPコネクション確立**(3-way handshake) 2. **データベース層ハンドシェイク**(MySQL: Connection Phase / PostgreSQL: Message Flow) 3. **認証** 4. **プロセス/スレッド生成**(データベースサーバ側) 都度接続ではTCPウィンドウサイズが毎回初期値からスタートするため、常時接続と比べてスループットが低下する。 C/S型RDBMSはもともと少数クライアントとのステートフルな通信向けに設計されており、多数クライアントとの接続/切断繰り返しとはインピーダンスミスマッチがある。 ## 接続モデルの3分類 ### 1. リクエスト都度接続モデル リクエスト処理の開始時に接続し、終了時に破棄する。 **特徴**: - オブジェクト管理が容易(ライフサイクルがリクエストに対応) - 接続ごとのオーバヘッドが毎回発生 - Perlのモダンな実装例: Plack::Middleware + Scope::Container::DBI ### 2. 常時接続モデル グローバル空間にDBハンドラオブジェクトを保持し、複数リクエストで使い回す。PreforkモデルのWebサーバでは各ワーカープロセスが独立して保持する。 **メリット**: 接続確立のオーバヘッドを削減できる。 **デメリット**: - メモリリークの温床になる - 切断検出と再接続の実装が必要 - L4ロードバランサ(LVS/HAProxy)経由では均等分散が困難(接続が切れないため振り分け先固定) - DBフェイルオーバ時の再接続に時間がかかる。TCPが切れるまで待たされる場合も。 Perlの場合、DBIの `connect` 返り値をそのままキャッシュしても切断後に再接続しない。`connect_cached` や `Scope::Container::DBI` を使うこと。 ### 3. コネクションプーリング 常時接続の発展形。接続数の管理を加えることでデータベース側の制限超過を防ぐ。詳細は[[コネクションプーリング]]を参照。 ## データベース別の温度感 | | PostgreSQL | MySQL | |---|---|---| | 接続アーキテクチャ | 1接続=1プロセス(fork) | 1接続=1スレッド(Thread Cache再利用) | | 接続コスト | **高い**(プロセス生成・メモリ確保) | 低い(Thread Cacheで再利用) | | 推奨手法 | プロキシ型プーリング([[PgBouncer]] / [[Pgpool]])| 都度接続が多い | ## ロードバランサとの関係 常時接続では接続が永続するため、L4ロードバランサ(LVS/HAProxy)が均等に振り分けられない。サーバメンテナンス時は重みを0にして既存接続が切れるのを待つ必要がある。 ## 横断的知見 - 今後の取り込みで、複数ソース間の関係を追記する。 ## 未解決の問い - この概念をどのソース群で継続的に検証するか。 ## 関連 - 発展概念: [[コネクションプーリング]] - 主要エンティティ: [[PgBouncer]] / [[Pgpool]] - 一次出典: [[@2015__yuuk.io__architecture-of-database-connection]]