症状
MySQLに接続しようとすると「ERROR 1040 (HY000): Too many connections」が表示される
結論:まずこれを確認
- 現在の接続数を確認:
SHOW STATUS LIKE 'Threads_connected'; - 最大接続数を確認:
SHOW VARIABLES LIKE 'max_connections'; - 不要な接続があれば切断、なければ
max_connectionsを一時的に増やす
トラブルシューティングフロー
flowchart TD
A[Too many connections発生] --> B{MySQLに接続できる?}
B -->|Yes| C[接続数を確認]
B -->|No| D[rootで緊急接続を試行]
C --> E{接続数が上限に近い?}
E -->|Yes| F{不要な接続がある?}
E -->|No| G[別の原因を調査]
F -->|Yes| H[不要な接続を切断]
F -->|No| I[max_connectionsを増やす]
D --> J{緊急接続できた?}
J -->|Yes| C
J -->|No| K[MySQLプロセスを確認]
H --> L[根本原因を調査]
I --> L
よくある原因
- アプリケーションの接続リーク - 接続を閉じずに放置しているコードがある
- max_connections が小さすぎる - デフォルト値(151)がアクセス量に対して不足
- スロークエリによる接続滞留 - 遅いクエリが接続を長時間占有している
- コネクションプールの設定ミス - プールサイズが大きすぎる、またはリーク
- 急激なアクセス増加 - 想定外のトラフィックスパイク
- バッチ処理の同時実行 - 複数のバッチが同時に大量接続を生成
- 監視ツールの過剰接続 - 監視システムが多数の接続を維持している
確認手順
ステップ1: MySQLに接続できるか確認する
mysql -u root -p -e "SELECT 1"
🔍 チェックポイント: 接続できれば次のステップへ。接続できない場合はステップ1-Bへ
ステップ1-B: 緊急接続を試行する
rootユーザーには追加で1接続分の予約枠がある:
mysql -u root -p --host=127.0.0.1 --protocol=tcp
🔍 チェックポイント: これでも接続できない場合はMySQLプロセス自体を確認
ステップ2: 現在の接続状況を確認する
mysql -u root -p -e "SHOW STATUS LIKE 'Threads_connected';"
mysql -u root -p -e "SHOW VARIABLES LIKE 'max_connections';"
🔍 チェックポイント: Threads_connected が max_connections に近い値なら接続数上限が原因
ステップ3: 接続元を特定する
mysql -u root -p -e "SELECT user, host, db, command, time, state FROM information_schema.processlist ORDER BY time DESC;"
🔍 チェックポイント: 同一ユーザー/ホストからの大量接続、長時間の Sleep 接続がないか確認
ステップ4: 不要な接続を切断する
Sleep状態で長時間経過した接続を確認:
mysql -u root -p -e "SELECT id, user, host, db, command, time FROM information_schema.processlist WHERE command = 'Sleep' AND time > 300;"
特定の接続を切断:
mysql -u root -p -e "KILL <process_id>;"
🔍 チェックポイント: 切断後に Threads_connected が減少することを確認
ステップ5: max_connections を一時的に増やす(応急処置)
mysql -u root -p -e "SET GLOBAL max_connections = 300;"
🔍 チェックポイント: 再起動すると元に戻る。恒久対応は設定ファイルで行う
ステップ6: 設定ファイルで恒久対応する
/etc/mysql/mysql.conf.d/mysqld.cnf または /etc/my.cnf を編集:
[mysqld]
max_connections = 300
設定反映:
sudo systemctl restart mysql
🔍 チェックポイント: 再起動後に SHOW VARIABLES LIKE 'max_connections'; で反映を確認
NG行動
- むやみに max_connections を大きくする - メモリ不足でMySQLがクラッシュする可能性がある
- プロセスを無差別にKILLする - 実行中のトランザクションが中断しデータ不整合の原因になる
- MySQLを即座に再起動する - 根本原因が解消されず再発する、またはデータ損失の可能性
- wait_timeout を極端に短くする - 正常な接続まで切断される
よくある質問(FAQ)
Q1: max_connections の適正値はいくつ?
A: 環境による。目安として「同時接続数の1.5〜2倍」から開始し、監視しながら調整する。メモリ使用量(1接続あたり約1MB〜10MB)も考慮が必要。
Q2: 接続リークはどうやって見つける?
A: SHOW PROCESSLIST で Sleep 状態が長時間続く接続を確認。アプリケーション側のコネクション管理コードをレビューし、try-finally や using で確実に接続を閉じているか確認する。
Q3: コネクションプールを使っているのになぜ発生する?
A: プールサイズの設定ミス、複数アプリケーションからの接続、プール自体のリークが考えられる。各アプリケーションのプール設定を確認し、合計が max_connections を超えていないか確認する。
関連するエラー・症状
準備中
解決しない場合
- MySQL公式ドキュメント - Server System Variables
- 確認すべきログ:
/var/log/mysql/error.log - 次に調べるキーワード:「MySQL connection pool leak」「MySQL wait_timeout」「MySQL max_connections memory」