「Too many connections」でMySQLに接続できないときの対処|接続上限の見直しとコネクション滞留の調査

宮崎智広 この記事の監修:宮崎智広(Linux実務・教育歴20年以上・受講者3,100名超)
HOMELinux技術 リナックスマスター.JP(Linuxマスター.JP)Linuxtipsデーターベース管理 > 「Too many connections」でMySQLに接続できないときの対処|接続上限の見直しとコネクション滞留の調査
「MySQLに接続しようとしたら、突然つながらなくなった」
「アプリのエラーログに 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 のセット設定が基本


「このままじゃマズい」と感じていませんか?
参考書を開く気力もない、同年代に取り残される不安——
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

「Too many connections」エラーの意味と発生メカニズム

MySQLには、同時に受け入れられるクライアント接続数の上限を定めるシステム変数 max_connections があります。この上限に達すると、それ以降の接続要求はすべて拒否され、次のエラーが返されます。

ERROR 1040 (HY000): Too many connections

MySQL 8.0 のデフォルト値は 151 です。ただし、このうち1接続分は 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';

RHEL 9.4 上の MySQL 8.0.36 で実行した出力例です。

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)

この例では、上限 151 に対して現在 148 接続が張られており、過去に 151 本まで到達した履歴があります。Max_used_connectionsmax_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

特定のアプリサーバーのIPからの接続が突出して多い場合、そのサーバーでコネクションリークが起きている可能性があります。

即時対処法——接続上限を一時的に引き上げる

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 GLOBALSET 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;

メンテナンス窓口で MySQL を再起動できる場合は、my.cnf 変更後に再起動して設定を確定させてください。

# 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)』を完全無料でプレゼントしています。

無料メルマガで学習を続ける

Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。

登録無料・いつでも解除できます

暗記不要・1時間後にはサーバーが動く

3,100名以上が実践した「型」を無料で公開中

プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。

姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

Linux無料マニュアル(図解60P) 名前とメールで30秒登録
宮崎 智広

この記事を書いた人

宮崎 智広(みやざき ともひろ)

株式会社イーネットマーキュリー代表。現役のLinuxサーバー管理者として20年以上の実務経験を持ち、これまでに累計3,100名以上のエンジニアを指導してきたLinux教育のプロフェッショナル。「現場で本当に使える技術」を体系的に伝えることをモットーに、実践型のLinuxセミナーの開催や無料マニュアルの配布を通じてLinux人材の育成に取り組んでいる。

趣味は、キャンプにカメラ、トラウト釣り。好きな食べ物は、ラーメンにお酒。休肝日が作れない、酒量を減らせないのが悩み。最近、ドラマ「フライトエンジェル」を観て涙腺が崩壊しました。