MySQL 8.0+ 的 failed_login_attempts 策略仅对 caching_sha2_password 插件用户有效,需显式创建或修改用户时指定 FAILED_LOGIN_ATTEMPTS 和 PASSWORD_LOCK_TIME 参数,单位分别为次数和天(支持小数),锁定期满不自动解锁,必须成功登录才重置计数;错误码 ERROR 3956 表示已锁定,ERROR 1045 表示密码错误但未达阈值。

MySQL 8.0+ 自带的 failed_login_attempts 策略能用,但仅限于使用 caching_sha2_password 插件的账户
MySQL 原生不支持“锁定账户”这种操作系统级行为,它的“锁定”实际是拒绝认证——用户仍可连接,但身份验证失败后直接断开。这个功能依赖插件和密码策略模块,mysql_native_password 不支持该策略。
启用前先确认你的 MySQL 版本 ≥ 8.0.19(早期 8.0 版本可能缺失部分策略参数),并检查默认认证插件:
SELECT @@default_authentication_plugin;
如果不是 caching_sha2_password,需在创建用户时显式指定:
CREATE USER 'u1'@'%' IDENTIFIED WITH caching_sha2_password BY 'p1';
- 必须用
CREATE USER或ALTER USER ... IDENTIFIED WITH显式绑定插件,不能靠全局 default 覆盖已有用户 - 已存在的
mysql_native_password用户需先ALTER USER ... IDENTIFIED WITH caching_sha2_password BY 'xxx'迁移,否则策略无效 - 策略只对新连接生效;已建立的连接不受影响
设置连续失败 5 次锁定:用 FAILED_LOGIN_ATTEMPTS 和 PASSWORD_LOCK_TIME
这两个参数属于 MySQL 的 password_policy 机制,通过 ALTER USER 设置,不是全局变量,也不能写进 my.cnf。
例如锁定 5 次后禁用 1 小时:
ALTER USER 'u1'@'%' FAILED_LOGIN_ATTEMPTS 5 PASSWORD_LOCK_TIME 1;
-
FAILED_LOGIN_ATTEMPTS是整数,最小为 1;设为 0 表示禁用该策略 -
PASSWORD_LOCK_TIME单位是「天」,支持小数:0.04167≈ 1 小时,0.0007≈ 1 分钟;设为0表示永久锁定(需 DBA 手动解锁) - 若只要求“临时锁定”,别设成 0;否则用户无法自恢复,只能靠
ALTER USER ... ACCOUNT UNLOCK - 失败计数器在首次成功登录后自动重置;没有独立的“清空计数”命令
怎么知道账户被锁了?错误信息是 ERROR 3956 (HY000): Account is locked
当失败次数达到阈值后,下次尝试登录会立即报这个错,不会提示密码错误。这是关键区分点:
- 输错密码但未达阈值 →
ERROR 1045 (28000): Access denied for user - 已达阈值 →
ERROR 3956 (HY000): Account is locked - 账户被手动锁(
ACCOUNT LOCK)也会触发 3956,但和失败计数无关
查锁定状态可执行:
SELECT user, host, account_locked FROM mysql.user WHERE user = 'u1';
返回 Y 表示当前被锁(可能是策略触发,也可能是人工锁)。
解锁账户只有两种方式:等时间过期,或 DBA 手动执行 ALTER USER ... ACCOUNT UNLOCK
没有后台定时任务自动清理计数器,也没有配置项控制“冷却时间”。一旦锁住,只能被动等待 PASSWORD_LOCK_TIME 到期,或由有 CREATE USER 权限的管理员干预。
- 手动解锁命令:
ALTER USER 'u1'@'%' ACCOUNT UNLOCK; - 注意:解锁不重置失败计数器;如果刚解锁就再输错 1 次,它会从上次累计值继续(比如之前是 5/5,解锁后输错 1 次 → 立即又变 6/5 → 再锁)
- 想彻底清零计数器?MySQL 没提供接口。唯一办法是让该用户成功登录一次
生产环境若要求更精细的锁定控制(如 IP 维度、动态惩罚、图形化告警),得在应用层或中间件(如 ProxySQL、MaxScale)做补充,MySQL 原生能力到这里就到头了。


















