MySQLが「ストライキ」:SysAdminたちの眠れない夜
ある日の午前2時、システム監視をしていた時のことを鮮明に覚えています。顧客のウェブサイトが突然ダウンし、「Error establishing a database connection」という文字が表示されました。キーボードを叩く音よりも速く心臓が鼓動していました。調査の結果、コードのリークによる Too many connections エラーであることが判明しました。このような「火消し」の経験から学んだのは、パニックにならず、正しい場所から点検を始めることの大切さです。
データを破損(corrupt data)させる恐れがあるため、すぐにサーバーを再起動してはいけません。代わりに、具体的な症状から冷静に「診断」し、最も正確な解決策を導き出しましょう。
MySQLトラブル発生時の2つのアプローチ
通常、ITエンジニアが接続エラーに直面した際、次のいずれかの方法を選択します。
- 方法1:応急処置(消火活動): MySQLの再起動、ロックファイルの削除、あるいは根拠なく設定値を上げること。この方法はシステムを即座に復旧させますが、根本的な解決にはなりません。最悪の場合、ディスクに書き込まれていないバッファ内のデータを失う可能性もあります。
- 方法2:原因分析(Root Cause Analysis): エラーログの確認、ネットワークやユーザー権限のチェック。最初は少し時間がかかりますが、システムの長期的な安定につながります。
私は常に方法2を優先します。システムが完全に停止し、一時的に「息を吹き返させる」必要がある場合にのみ、サービスを維持するために方法1を使います。
—
1. Error 1045 (28000):認証情報の誤り、またはアクセス拒否
これは最も一般的なエラーです。パスワードの間違いや、現在のホストからのアクセス権限がない場合に発生します。正しいパスワードを入力していても、MySQLが 'root'@'localhost' と 'root'@'127.0.0.1' を厳密に区別しているためにブロックされることがあります。
解決方法:
もしrootパスワードを忘れてしまった場合は、MySQLを skip-grant-tables モードで起動してリセットします。
# サービスを停止
sudo systemctl stop mysql
# パスワードなしで一時起動
sudo mysqld_safe --skip-grant-tables &
# ログインして新しいパスワードに変更
mysql -u root
FLUSH PRIVILEGES;
ALTER USER 'root'@'localhost' IDENTIFIED BY 'NewPassword@2024';
注意: mysql データベース内の user テーブルを確認してください。 host カラムが、 localhost だけでなく、適切なIPからの接続を許可しているか確認しましょう。
—
2. Error 2002 (HY000):ソケットエラー、またはMySQLが未起動
このエラーは通常、クライアントが .sock ファイルを見つけられない場合に発生します。MySQLの突然のクラッシュや、ディスク容量がいっぱいでサービスが起動できないことが原因です。
解決方法:
まず、サービスの状態を確認します:
sudo systemctl status mysql
サービスが起動しているのにエラーが出る場合は、 my.cnf 設定ファイル内のソケットファイルの場所を確認します:
grep -r "socket" /etc/mysql/
痛い教訓:常に df -h と df -i コマンドを使用しましょう。以前、1時間も悩んだ末にサーバーのiノード(Inodes)が枯渇していたことに気づきました。ディスク容量があっても、MySQLがソケットファイルを作成できなくなっていたのです。
—
3. Error 1130 (HY000):リモート接続の拒否
MySQLはセキュリティ上、デフォルトでlocalhostのみをリッスン(listen)します。個人のPCから DBeaver や Navicat などのツールで接続したい場合は、この設定を変更する必要があります。
解決手順:
- 設定の修正:
mysqld.cnfファイルを開き、bind-address行を探します。127.0.0.1から0.0.0.0に変更します。 - ユーザー権限の付与: SQLを実行して、外部IPからの接続を許可します。
-- ユーザー 'dev_user' に全IPからの接続を許可(rootには非推奨)
CREATE USER 'dev_user'@'%' IDENTIFIED BY 'password';
GRANT ALL PRIVILEGES ON database_name.* TO 'dev_user'@'%';
FLUSH PRIVILEGES;
セキュリティのヒント: rootユーザーに対して '%' を使用しないでください。AWSやGoogle Cloudを使用している場合は、Security GroupやFirewallでポート3306を忘れずに開放してください。
—
4. 「Too many connections」エラー
これはシステムをスケールさせる際の悪夢です。MySQLのデフォルトの同時接続数は151です。各接続は約2MB〜10MBのRAMを消費します。むやみに増やすと、メモリ不足でサーバーがハングアップします。
根本的な解決:
すぐに max_connections を増やさないでください。まずは何がリソースを占有しているか確認しましょう:
SHOW PROCESSLIST;
もし何百もの接続が「Sleep」状態であれば、アプリケーションのコネクションプーリング(Connection Pooling)に問題があります。待ち時間を短縮して、MySQLが不要な接続を自動的に切断するように設定しましょう:
-- my.cnf での設定
[mysqld]
max_connections = 500
wait_timeout = 60
interactive_timeout = 60
秒間5000リクエストを処理するプロジェクトでは、ProxySQL を仲介役として導入しました。これにより接続の再利用が非常に効率的になり、ハードウェアをアップグレードすることなくMySQLの負荷を40%削減できました。
—
迅速な診断のためのチェックリスト
システムが接続エラーを報告するたびに、私はいつも以下の5つのステップを素早く確認します:
- ネットワーク: サーバーにPingが通りますか? ポート3306がファイアウォールでブロックされていませんか?
- サービス:
systemctl status mysqlコマンドの結果は正常(緑)ですか? - ログ:
/var/log/mysql/error.logの末尾100行を確認してください。原因の90%はここにあります。 - リソース: RAMがスワップ(swap)していませんか? ディスクの空き容量はありますか?
- 権限: ユーザーはそのIPからの接続権限を持っていますか?
エラーコードを理解していれば、一晩中悩む代わりに5分で問題を解決できます。データベース管理がスムーズに進み、深夜の緊急電話に悩まされることがなくなるよう願っています!

