执行mysqladmin flush-hosts可立即解封被阻塞IP,因它清空host cache并重置错误计数器;但若应用层持续触发失败连接(如错密码、连接池异常等),几分钟内将再次被拉黑。

MySQL 报 Host is blocked because of many connection errors,不是数据库坏了,而是它主动把你的 IP 拉黑了——错误计数器爆了,max_connect_errors 阈值被踩穿。临时清缓存能救急,但只要底层连接失败还在持续发生,几分钟后照样再报。
为什么刚 mysqladmin flush-hosts 完就又 blocked
这不是命令失效,是“止痛药治不了病根”。只要应用还在不断触发失败连接,host cache 里的计数器就会立刻重涨。常见真实场景包括:
- 应用配置里硬编码了错密码,每次启动或连接池重建都连一次就挂
- HikariCP 或 Druid 配了
connection-test-query,但 SQL 写错(比如写成SELECT 1而不是SELECT 1;),建连后立即执行失败 → 算作一次认证阶段错误 - Docker 容器重启后 IP 变了,但应用 DNS 缓存没刷新,仍用旧 hostname 或旧 IP 尝试连接(尤其
skip_name_resolve=OFF时,MySQL 会反解并按主机名匹配) - SLB 或防火墙在空闲时静默断开 TCP 连接,MySQL 收不到 FIN,认为是异常中断 → 计入错误
mysqladmin flush-hosts 执行失败的几种现实情况
看到 ERROR 1227 (42501): Access denied; you need (at least one of) the RELOAD privilege(s)?说明当前账号没权限。普通应用账号默认没有 RELOAD 或 SUPER 权限,根本执行不了这个操作。
- 最稳妥:用
root或 DBA 账号本地登录后执行FLUSH HOSTS; - 连不上数据库时唯一可用路径:用
mysqladmin -uroot -p flush-hosts(注意密码含特殊字符时建议交互式输入,避免 shell 解析出错) - Docker 环境下:用
docker exec mysql-db mysqladmin -uroot -p'xxx' flush-hosts,确保容器名和密码正确 - 极端无高权账号?可尝试绕过:
SET GLOBAL max_connect_errors = 99; SET GLOBAL max_connect_errors = 100;—— MySQL 内部会重置当前活跃 session 对应 host 的错误计数,但不保证 100% 可靠,仅作应急
怎么确认到底是哪个 IP 被 block、错几次了
MySQL 8.0+ 可直接查 performance_schema.host_cache,但需要 PROCESS 权限;老版本只能间接推断。优先执行这三步:
- 看阈值:
SHOW VARIABLES LIKE 'max_connect_errors'; - 8.0+ 精确查被 block 的记录:
SELECT HOST, SUM_CONNECT_ERRORS, FIRST_SEEN, LAST_SEEN FROM performance_schema.host_cache WHERE SUM_CONNECT_ERRORS > 0; - 如果没
PROCESS权限,用SELECT SUBSTRING_INDEX(host,':',1) AS ip, COUNT(*) AS errors FROM information_schema.processlist GROUP BY ip;辅助判断(注意这只是当前活跃连接 IP 汇总,非错误计数)
永久解决必须盯住应用层日志里的“第一次失败”
调高 max_connect_errors 到 1000 甚至 5000,只是把问题延后;flush-hosts 是秒级解封,但几小时内大概率复发。真正要做的,是翻应用启动日志、连接池初始化日志、以及 MySQL 错误日志(log_error 配置项指定路径),找那个最早的、未被掩盖的原始失败原因:
- 是不是 Spring Boot 启动时 DataSource 初始化就报了
Access denied for user?那就先修密码或权限 - 是不是 HikariCP 的
initialization-fail-timeout设为 0,导致服务一启就狂发连接? - 有没有在 CI/CD 流水线里漏掉了数据库密码变量,导致测试环境反复用默认空密码去连?
host cache 是内存结构,不持久化;但只要应用不停止错误行为,它就会一遍遍重建黑名单。所以排查入口永远是“第一次连不上时,MySQL 错误日志里那条最靠前的 ERROR 行”。











