max_connect_errors 是一个 “安全护栏” 参数:
当某主机 连续 max_connect_errors 次连接失败 时,MySQL 会 永久屏蔽该主机,直到管理员手动 FLUSH HOSTS 或重启实例。
一、核心作用
注意:只有 握手阶段 的失败才算数;认证成功后的查询异常不计。
二、默认值与范围
10 次过于激进,100 次相对宽松,但仍需根据环境调整。
三、快速实验:一次真实的“封禁”
# 故意输错密码 101 次(>100)
for i in {1..101}; do
mysql -h127.0.0.1 -uroot -pwrong -e "select 1" 2>/dev/null
done
# 第 102 次连接触发屏蔽
mysql -h127.0.0.1 -uroot -p正确密码
ERROR 1129 (HY000): Host '127.0.0.1' is blocked because of many connection errors; unblock with 'mysqladmin flush-hosts'四、配置方法
1. 永久生效
[mysqld]
max_connect_errors = 10000 # 按需放大2. 动态调整(无须重启)
SET GLOBAL max_connect_errors = 10000;3. 手动解封
-- 方式 1:清空整个 host cache
FLUSH HOSTS;
-- 方式 2:只移除指定主机(8.0.23+)
FLUSH HOSTS '192.168.1.10';五、如何监控“即将被封禁”的主机
-- 当前错误计数器(Performance Schema)
SELECT host, ip, sum_connect_errors
FROM performance_schema.host_cache
WHERE sum_connect_errors > 0
ORDER BY sum_connect_errors DESC;
-- 传统方式
SHOW GLOBAL STATUS LIKE 'Connection_errors%';六、最佳实践
配置模板
[mysqld]
max_connect_errors = 100000 # 宽松策略
max_connections = 500 # 配合总连接数
host_cache_size = 628 # 8.0+ 可选,控制 host_cache 大小七、与 host_cache_size 的联动(8.0+)
当 host_cache_size 满后,MySQL 按 LRU 踢出旧记录,对应主机的错误计数也随之清空——变相自动解封。
因此 放大 host_cache_size 也能降低“误封”概率:
[mysqld]
host_cache_size = 628 # 按需放大
max_connect_errors = 100000 # 同一 IP 允许 10 万次失败八、常见疑问
设为 0 会禁用封禁吗?
不会,最小值是 1;想完全禁用需重新编译或使用skip-host-cache(也跳过 DNS 解析,慎用)。失败次数会持久化吗?
不会,仅存在于内存(host_cache),重启实例或FLUSH HOSTS立即清零。主从复制会受影响吗?
复制线程使用 用户表 中的账号, 同样受封禁规则约束;若复制 IP 被屏蔽,I/O 线程将报ERROR 1129。
解决:把max_connect_errors调高,或在从库配置FLUSH HOSTS的自动修复脚本。
九、一键巡检脚本
#!/bin/bash
# 检查是否有主机即将被封禁(阈值 80%)
mysql -N -e "
SELECT ip, sum_connect_errors, @@max_connect_errors,
ROUND(sum_connect_errors*100/@@max_connect_errors,1) AS pct
FROM performance_schema.host_cache
WHERE sum_connect_errors > @@max_connect_errors * 0.8;"配合告警系统,提前发现而非等业务报错。
十、总结口诀
“云原生环境一万起,内网一千莫忘记;握手失败才计数,成功立刻清清零。”
核心记忆点:max_connect_errors 是 “容错阈值” 而非 “安全壁垒”——在 NAT 与容器时代, 宁大勿小,配合 监控 + 自动 flush 才是正道。
评论