执行mysqladmin flush-hosts能立即恢复连接,因该命令清空MySQL内存中的host cache,重置所有IP的错误计数器,使被封IP退出拒绝列表;但需在主从各实例分别执行,且不解决密码错误、连接池异常等根本原因。

直接解锁最快的方式是执行 mysqladmin flush-hosts,但不解决根本问题;真正要稳住连接,得先定位错误来源,再决定是否调参或修代码。
为什么执行 flush hosts 就能恢复连接?
MySQL 内部维护一个 host cache,记录每个 IP 的失败连接次数(比如密码错、超时、认证失败)。一旦该 IP 的 SUM_CONNECT_ERRORS 超过 max_connect_errors(默认 100),就会被加入“拒绝列表”。FLUSH HOSTS 命令清空这个缓存,相当于重置计数器。
- 可在已登录的 MySQL 客户端中直接运行:
FLUSH HOSTS;(需RELOAD权限) - 也可用命令行工具:
mysqladmin -uroot -p -S /var/lib/mysql/mysql.sock flush-hosts - 注意:主从架构下,必须对所有涉及的 MySQL 实例都执行,否则只刷主库,从库仍会拒绝连接
max_connect_errors 改大是不是一劳永逸?
不是。调高只是掩盖症状,反而可能降低安全水位——比如暴力破解尝试更容易绕过封锁。
- 查看当前值:
SHOW VARIABLES LIKE 'max_connect_errors'; - 临时修改(重启失效):
SET GLOBAL max_connect_errors = 1000; - 永久修改需在
my.cnf中添加:max_connect_errors = 1000,然后重启 MySQL - 真正该做的是查清错误源头:是应用连错了密码?连接池配置了不存在的用户?还是网络抖动导致大量
Connection timeout被计入错误?
怎么快速确认哪个 IP 被锁、错了多少次?
MySQL 8.0+ 可查 performance_schema.host_cache 表,但需要 PROCESS 权限;低版本只能靠日志 + 推断。
- 先看报错里带的 IP,比如
Host '192.168.5.22' is blocked... - 登录 MySQL 后执行:
SELECT HOST, SUM_CONNECT_ERRORS FROM performance_schema.host_cache WHERE HOST = '192.168.5.22'; - 对比
max_connect_errors值,确认是否确实超限 - 若查不到记录,说明该主机尚未被缓存(比如刚触发封锁),可结合错误日志时间点反推
连接池或 ORM 配置不当最容易踩坑
很多团队在压测或上线后突然遇到这个报错,其实和数据库本身无关,而是客户端行为异常触发了阈值。
- Druid 连接池若配置了
testWhileIdle=false且validationQuery错误,会导致大量无效连接被创建又丢弃 - SQLAlchemy 使用
create_engine(..., pool_pre_ping=True)能提前探测失效连接,避免堆积错误 - Django 的
CONN_MAX_AGE=0在高并发下可能引发瞬时重连风暴,建议设为非零值并配合健康检查 - 任何自动重试逻辑(如重试 3 次密码错误)都可能在几秒内打满 100 次限额
最常被忽略的一点:这个机制只统计“连接建立阶段”的失败,和 SQL 执行无关。所以日志里看到大量 OperationalError: (2003, "Can't connect to MySQL server") 或 (1045, "Access denied") 才是真凶,而 1064 或 1146 这类查询错误不会触发封锁。


















