max_connect_errors 是一个 “安全护栏” 参数:
当某主机 连续 max_connect_errors 次连接失败 时,MySQL 会 永久屏蔽该主机,直到管理员手动 FLUSH HOSTS 或重启实例。


一、核心作用

场景

触发条件

结果

密码错误、协议包异常、SSL 握手失败…

连续失败max_connect_errors

该主机被 加入 host_cache 黑名单,拒绝后续任何连接

正常连接成功

任意时刻

对应主机的错误计数器 清零

注意:只有 握手阶段 的失败才算数;认证成功后的查询异常不计。


二、默认值与范围

版本

默认值

范围

5.7 及以前

10

1~2<sup>-1

8.0+

100

同上

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%';

字段

含义

Connection_errors_max_connections

超过 max_connections 导致的失败

Connection_errors_select

握手阶段其他错误(含 max_connect_errors 触发)


六、最佳实践

环境

推荐值

理由

公有云 / Docker

10 000 ~ 100 000

NAT/负载均衡器前端大量容器复用同一出口 IP,极易“误杀”

内网微服务

1 000 ~ 10 000

服务重启、健康检查频繁,允许一定失败

堡垒机 / DBA 人工

100 ~ 1 000

人为操作少,保留基本防护

脚本/CI 频繁拉取

≥ 100 000

自动化测试环境密码轮换、重试逻辑会导致快速累计失败

配置模板

[mysqld]
max_connect_errors = 100000     # 宽松策略
max_connections = 500           # 配合总连接数
host_cache_size = 628           # 8.0+ 可选,控制 host_cache 大小

七、与 host_cache_size 的联动(8.0+)

参数

作用

host_cache_size

最多缓存多少条主机记录(默认 128)

max_connect_errors

单条记录的错误上限

host_cache_size 满后,MySQL 按 LRU 踢出旧记录,对应主机的错误计数也随之清空——变相自动解封
因此 放大 host_cache_size 也能降低“误封”概率

[mysqld]
host_cache_size = 628        # 按需放大
max_connect_errors = 100000  # 同一 IP 允许 10 万次失败

八、常见疑问

  1. 设为 0 会禁用封禁吗?
    不会,最小值是 1;想完全禁用需重新编译或使用 skip-host-cache(也跳过 DNS 解析,慎用)。

  2. 失败次数会持久化吗?
    不会,仅存在于内存host_cache),重启实例或 FLUSH HOSTS 立即清零。

  3. 主从复制会受影响吗?
    复制线程使用 用户表 中的账号, 同样受封禁规则约束;若复制 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;"

配合告警系统,提前发现而非等业务报错。


十、总结口诀

“云原生环境一万起,内网一千莫忘记;握手失败才计数,成功立刻清清零。”

场景

推荐值

是否需要监控

公有云 / K8s

100 000

内网服务

10 000

开发测试

1 000

⚠️

堡垒机

100

⚠️

核心记忆点
max_connect_errors“容错阈值” 而非 “安全壁垒”——在 NAT 与容器时代, 宁大勿小,配合 监控 + 自动 flush 才是正道。