mysql 8.0+ 中账号锁定状态需查 mysql.user 表的 account_locked 字段,y 表示锁定,n 不代表可用,还需检查 password_expired 等;锁定/解锁必须用 alter user,不可 update;唯一锁定报错是 error 3956。

如何用 SQL 查看用户账号是否被锁定
MySQL 8.0+ 中,账号锁定状态存在 mysql.user 表的 account_locked 字段里,不是靠密码过期或登录失败次数“自动体现”——得查表才知道。很多 DBA 以为 SHOW GRANTS FOR 'u'@'h' 能看到锁定状态,其实它完全不返回这个信息。
执行这条语句确认当前状态:
SELECT user, host, account_locked FROM mysql.user WHERE user = 'your_user';
-
account_locked值为Y表示已被锁定(手动或策略触发) - 值为
N不代表“绝对可用”,还要检查password_expired、password_last_changed和账户是否存在 - MySQL 5.7 及更早版本没有
account_locked字段,锁定靠插件(如validate_password)或外部逻辑模拟,查不到原生字段
锁定用户:用 ALTER USER 还是 UPDATE mysql.user?
必须用 ALTER USER,直接 UPDATE mysql.user 不生效,还会导致权限缓存不一致甚至后续无法登录。
正确操作只有这一种:
ALTER USER 'baduser'@'%' ACCOUNT LOCK;
- 解锁对应命令是
ALTER USER 'baduser'@'%' ACCOUNT UNLOCK; - MySQL 8.0.19+ 支持带条件锁定:
ALTER USER 'u'@'h' FAILED_LOGIN_ATTEMPTS 3 PASSWORD_LOCK_TIME 1;,但该策略需提前启用lock_option插件并配置全局变量 - 注意:执行后必须跟
FLUSH PRIVILEGES;吗?不需要。MySQL 8.0+ 的ALTER USER会自动重载权限系统
常见误判:“连接被拒”不等于账号被锁
报错 ERROR 1045 (28000): Access denied for user 是最模糊的提示,背后可能有七八种原因,账号锁定只是其中之一。
- 先排除网络和 host 匹配问题:
SELECT user, host FROM mysql.user WHERE user = 'x';看 host 是否匹配客户端来源 IP 或域名 - 检查认证插件:
SELECT plugin FROM mysql.user WHERE user = 'x';若是caching_sha2_password但客户端不支持,也会报 1045 - 确认密码是否为空或被重置过:
authentication_string字段为空字符串或*开头哈希值异常,都可能导致拒绝,和account_locked无关 - 真正由锁定引发的错误是
ERROR 3956 (HY000): Account is locked—— 这个错误码才是唯一可靠信号
自动化巡检时怎么安全判断异常用户
不能只查 account_locked = 'Y' 就发告警。生产环境里,有些账号本就该长期锁定(比如模板账号、保留测试账号),盲目告警反而干扰判断。
- 建议加白名单过滤:
WHERE account_locked = 'Y' AND user NOT IN ('backup', 'monitor', 'schema_maint') - 结合登录失败日志判断是否突发异常:查询
performance_schema.events_statements_summary_by_account_by_event_name中statement/sql/Connect的错误计数(需开启相关消费者) - 注意权限限制:普通账号查
mysql.user会提示ERROR 1142 (42000): SELECT command denied,巡检脚本必须用具备SELECT ON mysql.*的账号运行
账号状态不是非黑即白的开关,account_locked 只控制登录入口,不影响已存在的连接、复制线程或事件调度器任务。别在半夜因为一个被锁的监控账号就重启 mysqld。











