症状

MySQLに接続しようとすると「ERROR 1040 (HY000): Too many connections」が表示される

結論:まずこれを確認

  1. 現在の接続数を確認:SHOW STATUS LIKE 'Threads_connected';
  2. 最大接続数を確認:SHOW VARIABLES LIKE 'max_connections';
  3. 不要な接続があれば切断、なければ 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_connectedmax_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-finallyusing で確実に接続を閉じているか確認する。

Q3: コネクションプールを使っているのになぜ発生する?

A: プールサイズの設定ミス、複数アプリケーションからの接続、プール自体のリークが考えられる。各アプリケーションのプール設定を確認し、合計が max_connections を超えていないか確認する。

関連するエラー・症状

準備中

解決しない場合