# データベース接続モデル
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]]