タイトル: Host '...' is blocked because of many connection errors; unblock with 'mysqladmin flush-hosts'
SEOタイトル: MySQL「Host is blocked because of many connection errors」の解除と恒久対策
| この記事の要点 |
|
エラー内容
ERROR 1129 (HY000): Host '192.168.1.10' is blocked because of many
connection errors; unblock with 'mysqladmin flush-hosts'
MySQL は同一クライアントホストからの接続失敗(プロトコルエラー、ハンドシェイクタイムアウト、認証失敗)が max_connect_errors 回続くと、そのホストをホストキャッシュ上でブロックします。以降そのホストからは認証画面に到達する前に 1129 エラーで弾かれます。
即時解除
方法 A: mysqladmin から
# 別のホスト(許可済み)または localhost から
mysqladmin -u root -p flush-hosts
方法 B: SQL で
-- MySQL 5.7
FLUSH HOSTS;
-- MySQL 8.0.23 以降は FLUSH HOSTS が非推奨
TRUNCATE TABLE performance_schema.host_cache;
-- どちらも RELOAD(FLUSH HOSTS)または SYSTEM_VARIABLES_ADMIN 権限が必要
ホストキャッシュを確認する
MySQL 5.7+ は performance_schema.host_cache でブロック理由を SQL で確認できます:
SELECT IP, HOST, HOST_VALIDATED, COUNT_HANDSHAKE_ERRORS,
COUNT_AUTHENTICATION_ERRORS, COUNT_LOCAL_ERRORS,
SUM_CONNECT_ERRORS
FROM performance_schema.host_cache;
-- COUNT_HANDSHAKE_ERRORS: プロトコル不一致(古いクライアント等)
-- COUNT_AUTHENTICATION_ERRORS: 認証失敗
-- COUNT_LOCAL_ERRORS: サーバ内部エラー
-- SUM_CONNECT_ERRORS: max_connect_errors と比較されるカウンタ
max_connect_errors を上げる
既定値の 100 はリトライ多めの本番アプリでは小さすぎます:
-- 現在値確認
SHOW VARIABLES LIKE 'max_connect_errors';
-- 動的変更(再起動まで有効)
SET GLOBAL max_connect_errors = 10000;
恒久化するなら my.cnf に追記:
# /etc/mysql/mysql.conf.d/mysqld.cnf
[mysqld]
max_connect_errors = 10000
# DNS 逆引きを完全に無効化(後述)
skip-name-resolve
# ハンドシェイクのタイムアウト緩和
connect_timeout = 10
根本原因の調査
| 典型原因 | 確認 | 対処 |
|---|---|---|
| アプリのリトライ暴走 | アプリログで再接続ループ | 指数バックオフ実装、接続プール使用 |
| DNS 逆引きタイムアウト | host_cache の COUNT_HOST_BLOCKED_ERRORS | skip-name-resolve |
| FW / SG でタイムアウト | TCP 接続自体が timeout | セキュリティグループ・iptables 確認 |
| ロードバランサのヘルスチェック | 定期的に接続失敗 | ヘルスチェックを TCP のみ or 専用ユーザー |
| クライアントが古すぎる | HANDSHAKE_ERRORS 多い | クライアントライブラリ更新 |
DNS 逆引きを無効化(skip-name-resolve)
MySQL は接続元 IP を逆引きしてホスト名を取得しようとします。逆引きが遅い / 失敗するとハンドシェイクタイムアウトでカウントされます。
# my.cnf
[mysqld]
skip-name-resolve
注意: skip-name-resolve を有効化すると、'user'@'hostname' 形式の権限は機能しなくなります。IP で再定義が必要:
-- 旧(ホスト名)
DROP USER 'app'@'app-server.example.com';
-- 新(IP / ワイルドカード)
CREATE USER 'app'@'10.0.1.%' IDENTIFIED BY 'secret';
GRANT ALL ON myapp.* TO 'app'@'10.0.1.%';
FLUSH PRIVILEGES;
クラウド DB(RDS / Aurora)でブロックされた場合
マネージド DB は root に直接 SSH できないため、別経路で SQL を流す:
- 同 VPC 内の許可済みインスタンスから接続できれば
FLUSH HOSTS;を実行 - RDS パラメータグループで
max_connect_errorsを大きく - どうしても接続できない場合はインスタンスの再起動(host_cache は揮発)
アプリ側の予防策
関連する設定変数
| 変数 | 既定値 | 役割 |
|---|---|---|
max_connect_errors | 100 | ブロック閾値 |
connect_timeout | 10 | ハンドシェイク待ち秒 |
max_connections | 151 | 同時接続上限 |
host_cache_size | auto | ホストキャッシュ容量 |
skip_name_resolve | OFF | DNS 逆引き無効化 |
FAQ
Q: 自分の IP がブロックされたら自分自身では解除できない?
A: そのとおりです。localhost や別ホストから FLUSH HOSTS を実行する必要があります。サーバへの SSH があれば mysql -u root -p でローカル接続して実行。
Q: 再起動でブロックは消える?
A: ホストキャッシュは揮発なので消えます。ただし根本原因(リトライ暴走など)を直さないとすぐ再発します。
Q: max_connect_errors を 0 にしたら無制限?
A: 動作の正確性のため非常に大きい値(例: 4294967295)を設定してください。0 は意味が異なります。