はじめに
PHPでDB接続を書くとき、こういうコードを書いていませんか?
$pdo = new PDO(...);
そしてリクエストごとに毎回実行。
一見問題なさそうですが、こう思ったことはないでしょうか?
👉 複数のプロセスが同時に接続したらどうなるのか?
この記事では、
- PDO接続の実態
- 同時アクセス時に何が起きるのか
- 接続プール(Connection Pool)とは何か
- なぜ重要なのか
を整理します。
結論
👉 DBは同時接続数に制限がある
👉 接続を増やしすぎると普通に壊れる
PDO接続の実態
$pdo = new PDO(...);
これは何をしているかというと:
👉 DBサーバーに新しい接続を1本張っている
問題:同時アクセス
例えば:
ユーザーA → リクエスト
ユーザーB → リクエスト
PHP(FPMなど)は:
👉 別プロセスで処理する
起きること
プロセスA → PDO接続①
プロセスB → PDO接続②
👉 接続が増える
さらに増えると
100リクエスト → 100接続
👉 DBサーバー:
- 接続数オーバー
- メモリ消費
- レスポンス低下
DB側の制限
MySQLには:
👉 max_connections
があります
例
max_connections = 151
👉 151以上は:
Too many connections
ここで勘違いしやすいこと
❌ 同時にMasterを見たら競合する?
👉 読み込み(SELECT)は基本問題なし
⭕ 本当の問題
👉 接続数の爆発
書き込みはどうなるか
INSERT / UPDATE
👉 MySQLは:
- ロック(行ロック / テーブルロック)
- トランザクション制御
で整合性を保つ
つまり
- 同時に来ても壊れない
- ただし遅くなる
接続プールとは
👉 接続を使い回す仕組み
イメージ
[接続1] ← 再利用
[接続2] ← 再利用
[接続3] ← 再利用
👉 新規接続を減らす
なぜ重要か
① 接続コストが高い
- TCP接続
- 認証
- 初期化
👉 毎回やると重い
② DBを守る
👉 接続数を制御できる
PHPの現実
ここ重要です👇
PHP(FPM)の場合
👉 基本的に接続プールはない
どうなるか
リクエストごとに接続作成 → 終了
対策
① 永続接続(Persistent Connection)
$pdo = new PDO($dsn, $user, $pass, [
PDO::ATTR_PERSISTENT => true
]);
注意
- 完全なプールではない
- プロセス単位で再利用
② 外部プーラを使う
例:
- ProxySQL
- PgBouncer(PostgreSQL)
👉 DBの前にプールを置く
③ 接続数を抑える設計
- 無駄な接続を作らない
- コネクションを使い回す
Master/Slaveとの関係
👉 接続はさらに増える
書き込み → Master
読み込み → Slave
👉 合計接続数が増加
本質
「同時アクセスの問題 = データ競合ではなくリソース競合」
まとめ
- PDOは接続を毎回作る
- 同時アクセスで接続数が増える
- DBには上限がある
- 接続プールで制御する
👉 「接続数」を意識するのが重要
おわりに
今回のポイントはこれです:
「クエリ」ではなく「接続」を意識する
SQLの最適化だけでなく、
- 接続数
- 同時実行数
を考えることで、システムの安定性は大きく変わります。