2026年9月16日
2026年9月16日
MySQLのmax_connections設定の最適化|適正値の決め方と確認手順
max_connections は、MySQL が同時に受け付けるクライアント接続数の上限です。「Too many connections」が出たからといって大きな値にすればよいわけではなく、実際に使われた接続数、アプリケーション側の同時実行数、サーバーのメモリの3つから適正値を決めるのが基本です。この記事では、現状の確認方法、必要な接続数の見積もり方、安全な変更手順、上限に達したときの原因の切り分けまでを順に説明します。
max_connections が足りないときの症状
上限に達すると、新しい接続は拒否されます。症状は次のような形で現れます。
- MySQL クライアントやアプリケーションのログに
ERROR 1040 (HY000): Too many connectionsが出る - WordPress の画面に「データベース接続確立エラー」が表示される
- 共有サーバーなどで
ERROR 1203 ... max_user_connectionsが出る(サーバー全体ではなく、ユーザーごとの上限に達している)
3つ目は別の設定で、max_connections を上げても解決しません。エラーの番号と文言を最初に確認してください。なお WordPress の「データベース接続確立エラー」は、パスワード違いや MySQL の停止でも同じ表示になるため、サーバーのエラーログや MySQL のログで実際の原因を確かめる必要があります。
現在の値と実際の使用状況を確認する
まず、設定値と、起動してから実際に使われた最大接続数を見比べます。
SHOW VARIABLES LIKE 'max_connections';
SHOW GLOBAL STATUS WHERE Variable_name IN (
'Max_used_connections',
'Threads_connected',
'Threads_running',
'Connection_errors_max_connections',
'Aborted_connects',
'Uptime'
);
見るべきポイントは次のとおりです。
- Max_used_connections:起動後に同時接続がもっとも多かった瞬間の数。max_connections に近い、または同じなら上限に当たった可能性が高い
- Connection_errors_max_connections:上限のせいで拒否された接続の累計。0 より大きければ実際に拒否が起きている
- Threads_connected と Threads_running:今つながっている数と、そのうち実際にクエリを実行中の数
- Uptime:これらの累計がどれくらいの期間のものか。再起動直後の数値はあまり参考にならない
MySQL と MariaDB の既定値は、主なバージョンではどちらも 151 です(2026年10月現在)。何も設定していないサーバーでは、この値のまま運用されていることがよくあります。
誰が接続しているかを調べる
上限に当たっている場合、値を上げる前に「何がそれだけ接続しているのか」を確認します。
SELECT user,
SUBSTRING_INDEX(host, ':', 1) AS client,
command,
COUNT(*) AS conns,
MAX(time) AS max_sec
FROM information_schema.PROCESSLIST
GROUP BY user, client, command
ORDER BY conns DESC;
結果の command 列の読み方がポイントです。
- Sleep が大量にある:接続したまま何もしていない接続がたまっている。持続的接続(パーシステント接続)を使うアプリケーションや、接続プール、長すぎる wait_timeout が疑われる
- Query が多く max_sec が大きい:遅いクエリが詰まって、後から来た接続が待たされている。この場合に max_connections を上げると、詰まりがさらにひどくなることがある
- 特定のホストやユーザーに偏っている:バッチ処理、バックアップ、監視ツール、別のアプリケーションが原因かもしれない
MySQL 8.0 では information_schema.PROCESSLIST は非推奨となり、performance_schema.processlist が推奨されています。上のクエリはテーブル名を置き換えればそのまま使えます。
必要な接続数を見積もる
WordPress は通常、1つのリクエストにつきデータベース接続を1本使い、リクエストが終われば閉じます。そのため、PHP 側で同時に動けるプロセス数が、必要な接続数の目安になります。
- PHP-FPM なら各プールの pm.max_children の合計(Web サーバーが複数台あれば全台分)
- WP-Cron、WP-CLI、バックアップ、監視、管理用のクライアントなど、Web 以外の接続
- 同じ MySQL を使う別のサイトやアプリケーション
これらの合計に少し余裕を足した値が出発点です。逆に、PHP 側の同時実行数が 50 程度なのに max_connections を 1000 にしても、使われない枠が増えるだけで、むしろ異常時に大量の接続を受け入れてサーバー全体を道連れにする原因になります。
メモリとの関係を確認する
接続ごとに、ソートや結合のためのバッファが必要に応じて確保されます。同時接続が増えるほど、これらのメモリが積み上がります。
SELECT @@innodb_buffer_pool_size / 1024 / 1024 AS buffer_pool_mb,
@@sort_buffer_size / 1024 AS sort_kb,
@@join_buffer_size / 1024 AS join_kb,
@@read_buffer_size / 1024 AS read_kb,
@@read_rnd_buffer_size / 1024 AS read_rnd_kb,
@@thread_stack / 1024 AS thread_stack_kb;
ざっくりした考え方は「全体で共有するメモリ(バッファプールなど)+ 接続ごとのバッファ × 同時に重いクエリを実行する接続数」です。接続ごとのバッファは必要になったときに確保され、1つのクエリで複数回確保されることもあるため、正確な計算式ではなく最悪の場合の目安として使ってください。この見積もりが物理メモリを超えるようなら、max_connections を上げる前にメモリの増設か、接続ごとのバッファの見直しが先です。メモリが足りなくなると、OS の OOM Killer に mysqld が強制終了されることがあります。
max_connections を変更する手順
変更前に、現在の設定ファイルをバックアップしてください。可能ならステージング環境で負荷をかけて確認してから本番に反映します。
一時的に変更する
SET GLOBAL max_connections = 300;
再起動すると元に戻ります。緊急時の応急処置や、値を試すときに使います。実行には SYSTEM_VARIABLES_ADMIN(または古い環境では SUPER)権限が必要です。
恒久的に変更する
設定ファイル(my.cnf や、/etc/mysql/mysql.conf.d/ 配下などディストリビューションごとの場所)の [mysqld] セクションに書きます。
[mysqld]
max_connections = 300
MySQL 8.0 以降では SET PERSIST max_connections = 300; でも永続化できます。この場合は mysqld-auto.cnf に保存され、設定ファイルより優先されるので、後で設定ファイルを直しても反映されないという混乱が起きがちです。どちらで管理するかを決めておくと安心です。
OS のファイル数上限に注意する
接続ごとにファイルディスクリプタを使うため、OS 側の上限が低いと、MySQL は起動時に max_connections を自動で下げます。エラーログに「Changed limits: max_connections」のような警告が出ていないか確認してください。systemd で動かしている場合は、サービスの上書き設定で LimitNOFILE を引き上げます。
# サービス名は環境により mysql / mysqld / mariadb など
sudo systemctl edit mysql
# 開いたファイルに以下を書いて保存
# [Service]
# LimitNOFILE=65535
sudo systemctl daemon-reload
sudo systemctl restart mysql
変更後は SHOW VARIABLES LIKE 'max_connections'; と SHOW VARIABLES LIKE 'open_files_limit'; で、意図した値になっているかを確かめます。
上限に達したときの調査方法
すでに接続が埋まっていると、調査のためにログインすることもできません。MySQL は CONNECTION_ADMIN(または SUPER)権限を持つユーザー用に、max_connections とは別に1本だけ接続を予約しています。管理者アカウントでログインして、原因を調べてください。WordPress 用のデータベースユーザーにこうした強い権限を与えていると、予約枠まで WordPress に使われてしまうので、アプリケーション用のユーザーは必要最小限の権限にしておきます。MySQL 8.0.14 以降では、管理用の別ポート(admin_address の設定)を用意する方法もあります。
原因が分かったら、次の順に対策を検討します。
- 遅いクエリが詰まっている:スロークエリログで該当クエリを特定し、インデックスやクエリを直す
- アクセス集中やボット:ページキャッシュやオブジェクトキャッシュで、データベースまで届くリクエストを減らす。不審なボットは Web サーバー側で制限する
- Sleep 接続がたまっている:持続的接続の設定を見直す。wait_timeout を下げる方法もあるが、長時間のバッチ処理が「MySQL server has gone away」で切れることがあるので慎重に
- 本当に同時実行数が足りない:見積もりとメモリを確認したうえで max_connections を上げる
接続のたびにスレッドが作られている場合は、Threads_created の増え方も見てください。急速に増えているなら thread_cache_size の見直しで接続処理の負担を減らせます。
マネージドサービスや共有サーバーの場合
Amazon RDS などのマネージドサービスでは、max_connections の初期値がインスタンスのメモリ量から計算されることが多く、変更はパラメータグループなどサービス独自の方法で行います。仕様は変わることがあるので、利用しているサービスの公式ドキュメントで確認してください。
共有レンタルサーバーでは、max_connections や max_user_connections を利用者が変更できないのが一般的です。この場合は、キャッシュの導入や重いプラグインの見直しで同時接続を減らすことが現実的な対策になります。
まとめ
- エラーの番号と文言で、max_connections と max_user_connections のどちらに当たっているかを区別する
- Max_used_connections と Connection_errors_max_connections で、実際に上限に当たっているかを確認する
- PROCESSLIST で誰が接続しているかを調べ、遅いクエリや Sleep 接続が原因なら値を上げる前にそちらを直す
- 適正値は PHP 側の同時実行数の合計に余裕を足して決め、メモリの見積もりと OS のファイル数上限も確認する
- 変更は SET GLOBAL で試し、設定ファイルか SET PERSIST のどちらかで管理する