failed_login_attempts 和 password_lock_time 必须成对设置且仅对 caching_sha2_password 用户生效;mysql 8.0.19+ 支持账号级自动锁定,但需同时启用 validate_password 插件、正确指定插件及参数,并通过 alter user 重新指定认证方式才能生效。

FAILED_LOGIN_ATTEMPTS 和 PASSWORD_LOCK_TIME 必须成对设置,且仅对 caching_sha2_password 用户生效
MySQL 8.0.19+ 才真正支持账号级自动锁定,但不是“开了就管用”。你设了 FAILED_LOGIN_ATTEMPTS 3 却没锁住,大概率是因为参数没配齐、插件不匹配,或者 validate_password 插件根本没启用。
- 必须同时指定两个参数:
FAILED_LOGIN_ATTEMPTS和PASSWORD_LOCK_TIME,缺一不可。单独执行ALTER USER ... FAILED_LOGIN_ATTEMPTS 3是静默无效的 - 用户认证插件必须是
caching_sha2_password或mysql_native_password(后者兼容性差,推荐前者) -
validate_password插件必须处于ACTIVE状态,否则失败计数根本不会触发——它不是用来校验密码强度的,而是为锁定逻辑提供底层钩子 - 已有用户不能只改策略:得连插件一起换,例如
ALTER USER 'u'@'%' IDENTIFIED WITH caching_sha2_password BY 'pwd' FAILED_LOGIN_ATTEMPTS 3 PASSWORD_LOCK_TIME 0.04167 -
PASSWORD_LOCK_TIME单位是「天」,锁 1 小时要写0.04167(1 ÷ 24),写0表示永久锁定,不是“不锁”
ACCOUNT LOCK 是开关式人工禁用,和自动锁定机制完全无关
别把 ACCOUNT LOCK 当成防爆破手段。它是管理员手动执行的硬关闭,执行后任何密码都拒绝登录,错误提示固定为 Access denied for user 'u'@'%' (using password: YES),但不会影响 failed_login_attempts 计数,也不会更新 account_locked 字段。
-
ACCOUNT LOCK和FAILED_LOGIN_ATTEMPTS冲突:若一个用户同时设了二者,MySQL 优先执行锁死行为,失败计数器压根不启动 - 解锁方式不同:
ACCOUNT LOCK只能靠ALTER USER ... ACCOUNT UNLOCK;而自动锁定需成功登录或手动ACCOUNT UNLOCK - 查状态时,
SELECT user, host, account_locked FROM mysql.user中该字段仍为N是正常现象,不代表没生效——验证必须用新连接实测
max_connect_errors 不是防暴力破解的参数,误配反而伤业务
这个参数常被误当成“输错几次就封号”,但它统计的是连接建立阶段的异常断开(比如握手包发一半就挂了),和密码输错完全无关。
- 它按 IP 统计,不是按账号;NAT 环境下多个用户共用一个出口 IP,会互相连坐
- 一旦触发,MySQL 把该 IP 加入
host_cache并拒绝所有后续连接(包括正确密码),恢复只能靠FLUSH HOSTS或重启 - 设太小(如
max_connect_errors = 3)会导致运维反复试错把自己锁在外面,且对代理层、容器环境完全失效
connection_control 插件可作为补充延迟手段,但不能替代账号锁定
如果你需要更细粒度的防护节奏(比如首次失败后等 1 秒、第二次等 3 秒),connection_control 插件能起作用,但它不锁定账号,只是增加攻击者重试成本。
- 需安装两个组件:
INSTALL PLUGIN connection_control SONAME 'connection_control.so'和INSTALL PLUGIN connection_control_failed_login_attempts SONAME 'connection_control.so' - 延迟单位是毫秒:
SET GLOBAL connection_control_min_connection_delay = 1000(1 秒起) - 它和原生
FAILED_LOGIN_ATTEMPTS可共存,但逻辑独立:前者拖慢尝试速度,后者直接封号 - 注意:该插件对 socket 连接、
auth_socket认证无效,且不记录具体用户名,仅基于 IP
真正防爆破得靠组合策略:核心账号用 ACCOUNT LOCK 人工管控,应用账号用 FAILED_LOGIN_ATTEMPTS 自动防护,再加 fail2ban 解析错误日志做系统级拦截。单靠 MySQL 内建机制,永远有绕过路径——比如空密码、本地 socket、或插件不匹配时的完全失效。











