MySQL 8.0+账号锁定需同时满足三条件:启用validate_password插件、用户认证插件为caching_sha2_password、FAILED_LOGIN_ATTEMPTS与PASSWORD_LOCK_TIME成对设置;缺一则account_locked恒为N。

MySQL 8.0+ 要用 VALIDATE_PASSWORD 插件配合 FAILED_LOGIN_ATTEMPTS 才行
MySQL 原生不支持“输错 N 次就锁账号”这种行为,VALIDATE_PASSWORD 插件只管密码强度,和登录失败无关。真正起作用的是 mysql.user 表里的 FAILED_LOGIN_ATTEMPTS 和 PASSWORD_LOCK_TIME 字段,但这两个字段**仅在启用 caching_sha2_password 认证插件且开启账户锁定策略时才生效**。
所以第一步必须确认你的用户用的是 caching_sha2_password(MySQL 8.0 默认),而不是 mysql_native_password:
SELECT User, Host, plugin FROM mysql.user WHERE User = 'your_user';
- 如果不是
caching_sha2_password,先改认证方式:ALTER USER 'your_user'@'%' IDENTIFIED WITH caching_sha2_password BY 'new_pass'; - 改完要
FLUSH PRIVILEGES; -
VALIDATE_PASSWORD插件不是必需的,别被网上教程误导——它和账号锁定完全无关
设置 FAILED_LOGIN_ATTEMPTS 必须用 CREATE USER 或 ALTER USER 显式指定
这个值不会自动继承全局配置,也不能通过修改 mysql.user 表直接写入(会报错或被忽略)。必须用 DDL 语句设置:
ALTER USER 'alice'@'localhost' FAILED_LOGIN_ATTEMPTS 3 PASSWORD_LOCK_TIME 1;
-
FAILED_LOGIN_ATTEMPTS 3:连续输错 3 次密码后锁定 -
PASSWORD_LOCK_TIME 1:锁定 1 天;设为0表示永久锁定,需 DBA 手动解锁 - 注意:该语法仅在 MySQL 8.0.19+ 支持;8.0.18 及更早版本不识别
FAILED_LOGIN_ATTEMPTS - 如果执行时报错
Unknown argument,大概率是版本太低,别硬试
输错后账号真被锁了,怎么验证和解锁
锁定状态不会在错误信息里明说,客户端通常只看到:Access denied for user 'alice'@'localhost' (using password: YES),和普通密码错一样。要确认是否被锁,查 mysql.user 表:
SELECT User, Host, account_locked, password_last_changed, password_lifetime FROM mysql.user WHERE User = 'alice';
- 被锁时
account_locked值为Y(不是YES,是单字母) - 解锁只能由有
CREATE USER权限的用户执行:ALTER USER 'alice'@'localhost' ACCOUNT UNLOCK; - 别试图用
UPDATE mysql.user SET account_locked = 'N'—— 不生效,还会破坏元数据一致性 - 锁定期间即使密码正确也无法登录,哪怕从本地 socket 连也一样
连接器、驱动和中间件可能掩盖真实错误原因
很多应用用连接池(比如 HikariCP、Druid)或 ORM(如 SQLAlchemy、MyBatis),它们会在后台反复重试连接。这时你看到的“账号被锁”,可能是某次重试触发了锁定,而之前几次失败根本没被日志捕获。
- 排查时先关掉应用,用
mysql -u alice -p手动测试,避免干扰 - 检查 MySQL 错误日志(
log_error配置项指定的路径),搜索Failed password或locked关键字 - 如果用了 ProxySQL 或 MaxScale,它们可能有自己的连接失败计数逻辑,和 MySQL 原生锁定不联动
-
PASSWORD_LOCK_TIME是按“天”算的,不是秒或小时,设0.5会四舍五入成1,别指望分钟级精度
FAILED_LOGIN_ATTEMPTS 就只是个摆设字段。


















