应执行SELECT HOST, IP, SUM_CONNECT_ERRORS, COUNT_HOST_BLOCKED_ERRORS FROM performance_schema.host_cache WHERE SUM_CONNECT_ERRORS > 0;该语句可精准查出被封禁的IP及其错误计数,需PROCESS权限,且仅在skip_name_resolve=OFF或启用host_cache时有效。

怎么查出到底是哪个 IP 被 block 了
MySQL 8.0+ 的真实阻塞状态全在 performance_schema.host_cache 里,不是靠猜、也不是翻错误日志。执行这句就能看到具体 IP 和当前错误计数:
SELECT HOST, IP, SUM_CONNECT_ERRORS, COUNT_HOST_BLOCKED_ERRORS FROM performance_schema.host_cache WHERE SUM_CONNECT_ERRORS > 0;
注意两点:
- 需要
PROCESS权限,普通应用账号通常没有,得用 DBA 或 root 执行 - 如果返回空,说明没被 block,问题不在 host cache,得往别处查(比如 DNS 解析失败、连接池复用旧连接、SSL 握手失败)
为什么 SHOW VARIABLES LIKE 'max_connect_errors' 没用
这个命令只告诉你阈值是多少,比如返回 100,但完全不告诉你谁超了、超了多少、是不是真 block 了。它就像告诉你“红灯亮起要停”,却不告诉你哪辆车闯了。
常见误操作包括:
- 在从库上查
host_cache,但应用实际连的是主库(或中间件路由到某台从库),数据不一致 - 用了
skip_name_resolve=ON,此时HOST字段存的是 IP,但你按主机名去查,查不到 - 容器化部署启动时加了
--skip-host-cache,整个缓存压根没开,FLUSH HOSTS自然无效
哪些错误会真正计入 SUM_CONNECT_ERRORS
只有连接建立阶段失败才算数,不是所有报错都算。重点区分:
- ✅ 算:密码错、用户名不存在、TCP 连接被防火墙/SLB 主动断开、DNS 解析超时导致握手失败
- ❌ 不算:连接成功后执行
SELECT * FROM nonexist_table报错、事务死锁、Lock wait timeout - ⚠️ 容易混淆:
connect_timeout超时会记一次错误;但wait_timeout或interactive_timeout超时不会
应用端怎么快速确认是不是自己惹的祸
别急着 flush,先看客户端行为是否异常:
- 检查连接字符串里
user和password是否写错,尤其注意密码含特殊字符时 URL 编码是否漏转义 - 连接池(如 HikariCP)是否开了
connection-test-query,而该 SQL 在目标库根本不存在或语法错误 - 是否在测试环境反复重启应用,每次启动都触发一次失败连接(比如配置中心未就绪,DB 配置为空)
- 用
tcpdump或Wireshark抓包看三次握手是否完成——如果 SYN 发出去没回 SYN-ACK,问题在网路或 mysqld 没监听
真正难定位的,往往是 DNS 反解慢 + skip_name_resolve=OFF 组合:MySQL 收到连接后尝试反向解析 IP 成主机名,卡住几秒后超时,直接记为一次失败。这种不会留明显日志,但 host_cache 里 SUM_CONNECT_ERRORS 会悄悄涨。


















