「アプリのエラーログに
Too many connections と出て、サービスが止まった」本番稼働中に
ERROR 1040 (HY000): Too many connections が発生すると、原因の特定と対処を素早くやらなければなりません。MySQLサーバーが受け入れられる同時接続数の上限に達すると、新しい接続はすべて拒否されます。アプリケーションのユーザーには「503エラー」や「接続タイムアウト」として見えているはずです。この記事では、
too many connections mysql エラーの原因と対処法を順を追って解説します。接続数の確認コマンド(SHOW VARIABLES / SHOW STATUS)、即時の上限引き上げ(SET GLOBAL)、my.cnfへの恒久設定、ゾンビ接続の調査と強制切断(SHOW PROCESSLIST / KILL)、アプリ側のコネクション管理改善まで、RHEL 9.4 / Ubuntu 24.04 LTS で動作確認した内容をもとに説明します。この記事のポイント
・「Too many connections」は max_connections 上限到達で発生する
・SET GLOBAL max_connections = 値; で再起動なしに即時変更できる
・ゾンビ接続は SHOW PROCESSLIST で特定し KILL コマンドで切断する
・恒久対処は my.cnf の max_connections と wait_timeout のセット設定が基本
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
「Too many connections」エラーの意味と発生メカニズム
MySQLには、同時に受け入れられるクライアント接続数の上限を定めるシステム変数max_connections があります。この上限に達すると、それ以降の接続要求はすべて拒否され、次のエラーが返されます。ERROR 1040 (HY000): Too many connections
SUPER 権限(MySQL 8.0では CONNECTION_ADMIN 権限)を持つ管理ユーザー専用に予約されています。つまり、一般ユーザーが同時に使えるのは最大150接続です。主な発生パターン
・コネクションリーク:アプリが DB 接続を使い終わっても
close() を呼ばずに放置する設計上のバグ・ゾンビ接続の滞留:長時間スリープしている接続が残り続け、上限を圧迫する
・アクセス急増:Webサーバーのワーカープロセスが急増し、各プロセスが接続を張る
・バッチ処理の多重起動:夜間バッチが想定外に並列で起動し、DB 接続を大量消費する
too many connections mysql エラーは、「上限値が低すぎる」か「接続が正しく解放されていない」か、あるいはその両方が原因です。どちらが主因かを確認してから対処することが重要です。
現在の接続数・上限値を確認するコマンド
まず現状を把握します。MySQL に接続できる管理ユーザー(rootなど)で次のコマンドを実行してください。1. 上限値と現在の接続数を確認する
-- 上限値(max_connections)を確認 SHOW VARIABLES LIKE 'max_connections'; -- 現在の接続数(Threads_connected)を確認 SHOW STATUS LIKE 'Threads_connected'; -- 過去の最大同時接続数(Max_used_connections)を確認 SHOW STATUS LIKE 'Max_used_connections';
mysql> SHOW VARIABLES LIKE 'max_connections'; +-----------------+-------+ | Variable_name | Value | +-----------------+-------+ | max_connections | 151 | +-----------------+-------+ 1 row in set (0.00 sec) mysql> SHOW STATUS LIKE 'Threads_connected'; +-------------------+-------+ | Variable_name | Value | +-------------------+-------+ | Threads_connected | 148 | +-------------------+-------+ 1 row in set (0.00 sec) mysql> SHOW STATUS LIKE 'Max_used_connections'; +----------------------+-------+ | Variable_name | Value | +----------------------+-------+ | Max_used_connections | 151 | +----------------------+-------+ 1 row in set (0.00 sec)
Max_used_connections が max_connections と同じ値になっているのは、実際に上限に達したことを示しています。接続状態の内訳を確認する(SHOW STATUS)
-- スレッドの状態サマリー SHOW STATUS LIKE 'Threads_%';
+-------------------------+-------+ | Variable_name | Value | +-------------------------+-------+ | Threads_cached | 8 | | Threads_connected | 148 | | Threads_created | 382 | | Threads_running | 3 | +-------------------------+-------+
Threads_running はクエリを実際に実行中の数です。Threads_connected との差が大きい場合、多数の接続がスリープ(待機)状態で滞留していることを示しています。2. OS側から MySQL 接続数を確認する(ss コマンド)
MySQL に接続できないほど逼迫している状況では、OS 側から TCP 接続数を確認する方法も有効です。ss コマンドで MySQL のデフォルトポート 3306 への接続数を数えられます。Linux のポート確認コマンド(ss / lsof)の詳細はこちらも参考にしてください。# count active connections to mysql port 3306 $ ss -tn 'dport = :3306' | wc -l # count by source ip address $ ss -tn 'dport = :3306' | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn
即時対処法——接続上限を一時的に引き上げる
MySQL が稼働中の状態でも、SET GLOBAL コマンドで max_connections を変更できます。再起動は不要で、即時に反映されます。-- 接続上限を 300 に引き上げる(SUPER 権限または CONNECTION_ADMIN 権限が必要) mysql> SET GLOBAL max_connections = 300; Query OK, 0 rows affected (0.00 sec) -- 設定が反映されたか確認 mysql> SHOW VARIABLES LIKE 'max_connections'; +-----------------+-------+ | Variable_name | Value | +-----------------+-------+ | max_connections | 300 | +-----------------+-------+
・
SET GLOBAL による変更は、MySQL を再起動すると元の値に戻ります(my.cnf に書いていないため)・上限を上げすぎるとメモリが不足する場合があります。接続1本あたり約 1MB のメモリを消費する目安で計算してください
・サーバーの物理メモリ量を考慮した上限値の設定方法は「my.cnfのチューニング設計」が参考になります
まず
SET GLOBAL でサービスを復旧させ、次の恒久対処を並行して進めるのが現場での定石です。
MySQLのトラブル対応、場当たりではなく「型」として身につけませんか?
too many connections mysql のエラーは、設定変更だけでは根本解決になりません。コネクション設計・メモリ設計・障害復旧の「型」を体系的に習得したい方へ、『Linuxサーバー構築入門マニュアル(図解60P)』を完全無料でプレゼントしています。
恒久対処法——my.cnf への max_connections 設定
SET GLOBAL の変更は再起動で消えます。恒久的に設定を維持するには、my.cnf(LinuxではCentOS/RHEL系は /etc/my.cnf 、Debian/Ubuntu系は /etc/mysql/mysql.conf.d/mysqld.cnf)の [mysqld] セクションに追記します。1. my.cnf を編集する
# /etc/my.cnf を編集(RHEL/CentOS 系) $ sudo vi /etc/my.cnf # /etc/mysql/mysql.conf.d/mysqld.cnf を編集(Ubuntu 系) $ sudo vi /etc/mysql/mysql.conf.d/mysqld.cnf
[mysqld] セクションに以下を追記します。[mysqld] max_connections = 300 wait_timeout = 600 interactive_timeout = 600
・max_connections:同時接続の最大数。サーバーの物理メモリと接続あたりのメモリ消費量(目安: 1接続 = 約1MB)をもとに設定する
・wait_timeout:非インタラクティブ接続(アプリからの接続)がスリープ状態で放置される最大秒数。デフォルト 28800(8時間)は長すぎる。600秒(10分)程度が実務での推奨値
・interactive_timeout:インタラクティブ接続(mysql コマンドラインなど)のスリープタイムアウト。wait_timeout と同じ値を設定しておくのが無難
2. 再起動なしで設定を反映する(my.cnf 変更後)
MySQL の再起動ができない場合、my.cnf を変更してからSET GLOBAL と SET SESSION の組み合わせで設定を即時反映できます。ただし、wait_timeout / interactive_timeout は既存の接続には遡及しません。新規接続から新しい値が適用されます。-- 再起動なしで wait_timeout を変更(新規接続から有効) mysql> SET GLOBAL wait_timeout = 600; mysql> SET GLOBAL interactive_timeout = 600; mysql> SET GLOBAL max_connections = 300;
# RHEL/CentOS 系 $ sudo systemctl restart mysqld # Ubuntu 系 $ sudo systemctl restart mysql
滞留・ゾンビ接続の調査と強制切断
max_connections を引き上げても、根本的なコネクションリークがあると再び上限に達します。ゾンビ接続(スリープ状態で長時間放置された接続)を特定して強制切断しましょう。1. SHOW PROCESSLIST で接続を一覧表示する
-- 全接続の一覧(SUPER権限がある場合) mysql> SHOW FULL PROCESSLIST;
+-----+-------+--------------------+--------+---------+------+-------+------+ | Id | User | Host | db | Command | Time | State | Info | +-----+-------+--------------------+--------+---------+------+-------+------+ | 102 | app | 192.168.1.10:51234 | myapp | Sleep | 3821 | | NULL | | 103 | app | 192.168.1.10:51235 | myapp | Sleep | 3819 | | NULL | | 104 | app | 192.168.1.11:49100 | myapp | Query | 0 | ... | SEL..| | 105 | root | localhost | NULL | Query | 0 | ... | SHOW | +-----+-------+--------------------+--------+---------+------+-------+------+
・Command:
Sleep 状態の接続が長時間放置されていないか・Time:秒数。数百~数千秒が続いている接続はゾンビ接続の疑いが強い
・Host:どのサーバーからの接続か。特定のIPに集中していないか
2. 長時間スリープの接続を絞り込む
information_schema.processlist を使うと、スリープ時間で絞り込めます。-- スリープ時間が 600 秒以上の接続を一覧表示 SELECT id, user, host, db, command, time, state FROM information_schema.processlist WHERE command = 'Sleep' AND time > 600 ORDER BY time DESC;
3. KILL コマンドで強制切断する
ゾンビ接続の ID が特定できたら、KILL コマンドで切断します。-- 接続 ID を指定して切断(Query を中断する場合) mysql> KILL 102; mysql> KILL 103; -- クエリのみ中断し、接続は維持する場合 mysql> KILL QUERY 102;
information_schema.processlist から ID を取り出して動的に実行する方法が効率的です。-- スリープ 600 秒以上の接続を一括 KILL(シェルで実行) $ mysql -u root -p -e " SELECT CONCAT('KILL ', id, ';') FROM information_schema.processlist WHERE command = 'Sleep' AND time > 600; " | grep KILL | mysql -u root -p
KILL を実行する際は、トランザクションが途中のものをロールバックする可能性があります。業務に影響しない時間帯に実施するか、対象 ID を慎重に確認してから実行してください。アプリ側の接続管理改善——コネクションプールと適切な切断処理
too many connections mysql エラーが繰り返し発生する場合、max_connections の引き上げは一時しのぎに過ぎません。アプリケーション側の接続管理を見直すことが根本解決になります。1. コネクションプールを導入する
コネクションプールとは、あらかじめ一定数の DB 接続を確保しておき、リクエストのたびに使い回す仕組みです。接続の確立(TCP ハンドシェイク + MySQL 認証)のコストを省けるため、パフォーマンスも向上します。代表的なコネクションプール実装を以下に示します。
・Python + SQLAlchemy:
pool_size(常時保持する接続数)と max_overflow(バースト時の上乗せ数)を設定する・Java + HikariCP:
maximumPoolSize でプール上限を設定。デフォルト 10 は小規模向けで、本番では要チューニング・PHP + PDO:PDO 自体にはプール機能がない。Apache/PHP-FPM の persistent connection か ProxySQL を使う
・Node.js + mysql2:
createPool() でプールを作成し、pool.getConnection() / connection.release() のセットを徹底する2. persistent connection の落とし穴を把握する
PHP のmysql_pconnect や PDO の ATTR_PERSISTENT を使うと、プロセスをまたいで接続を再利用できます。ただし、接続が正しく解放されないとゾンビ接続が大量に蓄積します。特に PHP-FPM の pm.max_children と MySQL の max_connections の掛け算を意識してください。# 必要な max_connections の目安 max_connections >= (Webサーバー数) x (pm.max_children) x (DB接続数/プロセス) # 例: 2台の Webサーバー x pm.max_children=50 x 接続1本 = 100 # これに余裕 20% を加えて max_connections = 120 以上に設定する
3. ProxySQL でコネクション管理を一元化する
中規模以上の本番環境では、アプリと MySQL の間に ProxySQL を挟む構成が有効です。ProxySQL がコネクションプーリングを担うため、アプリ側のコネクション管理が不完全でも、MySQL への接続数は ProxySQL が制御します。本記事のまとめ
「Too many connections」エラーの対処を、発生から根本解決まで段階別に整理します。| フェーズ | やること | コマンド・設定 |
|---|---|---|
| 状況確認 | 現在の接続数と上限値を確認 | SHOW VARIABLES LIKE 'max_connections'; |
| 状況確認 | 過去の最大接続数を確認 | SHOW STATUS LIKE 'Max_used_connections'; |
| 即時対処 | 接続上限を一時的に引き上げ | SET GLOBAL max_connections = 300; |
| 恒久対処 | my.cnf に max_connections を記述 | my.cnf の [mysqld] に max_connections = 300 |
| 恒久対処 | ゾンビ接続を自動切断 | my.cnf に wait_timeout = 600 を設定 |
| ゾンビ調査 | スリープ中の接続を一覧表示 | SHOW FULL PROCESSLIST; |
| ゾンビ切断 | 特定の接続を強制切断 | KILL [id]; |
| 根本改善 | アプリのコネクション管理を見直す | コネクションプール導入 / release() 徹底 |
too many connections mysql エラーは、「上限値の設定不足」と「コネクションリーク」が重なって起きるケースが大半です。
SET GLOBAL による即時対処と、my.cnf への恒久設定、そしてゾンビ接続の調査・強制切断をセットで実施することが重要です。アプリ側のコネクションプール設計まで見直せば、再発リスクを大幅に下げられます。MySQLの接続管理も含む、Linuxサーバー構築の「型」を体系的に身につけませんか?
too many connections mysql のような本番障害は、コマンドを知っているだけでは防げません。設計・監視・障害対応の「型」として身につけることが再発防止の鍵です。現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、『Linuxサーバー構築入門マニュアル(図解60P)』を完全無料でプレゼントしています。
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら
- 前のページへ:my.cnfのチューニング設計|innodb_buffer_pool_sizeとmax_connectionsを実メモリから決める
- この記事の属するカテゴリ:データーベース管理へ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。
登録無料・いつでも解除できます