能生效,但仅限MySQL 8.0.12及以上版本;锁定后新连接被拒并报ERROR 3118,需SYSTEM_USER权限执行,解锁用ACCOUNT UNLOCK,低版本需用ALTER USER设随机密码替代。

MySQL 8.0+ 中用 ALTER USER ... ACCOUNT LOCK 锁定账户是否生效?
能生效,但仅限 MySQL 8.0.12 及以上版本。低于该版本执行会报错 ERROR 1064 (42000):语法错误,因为旧版本根本不支持 ACCOUNT LOCK 子句。
锁定后,该用户仍可登录(比如通过已存在的连接),但新连接会被拒绝,并返回错误:ERROR 3118 (HY000): Access denied for user 'xxx'@'%' (account is locked)。
- 锁定不删除密码、权限或账号本身,只是加一道连接拦截
- 锁定状态对所有主机来源(
'user'@'%'或'user'@'192.168.%')统一生效 - 若用户有多个 host 段(如
'baduser'@'localhost'和'baduser'@'%'),需分别锁定
执行 ALTER USER ... ACCOUNT LOCK 前必须确认的权限
操作者必须拥有 SYSTEM_USER 权限(MySQL 8.0.12+ 新增),且不能是被锁定的同一账户——否则会触发循环拒绝。
常见错误:ERROR 1227 (42000): Access denied; you need (at least one of) the SYSTEM_USER privilege(s) for this operation。
-
root默认有该权限;普通 DBA 账户需显式授权:GRANT SYSTEM_USER ON *.* TO 'dba'@'%'; - 不能用
UPDATE mysql.user SET account_locked='Y'手动改表——这不会刷新内存缓存,也不触发权限校验逻辑 - 锁定后,
SELECT user, host, account_locked FROM mysql.user可查到值为Y
如何解锁被锁账户?用 ALTER USER ... ACCOUNT UNLOCK
语法对称,但容易漏掉 UNLOCK 后面没空格或拼错成 UNLOK,导致报错 ERROR 1064。
示例正确写法:
ALTER USER 'attacker_test'@'%' ACCOUNT UNLOCK;
注意:
- 解锁不需要
SYSTEM_USER权限以外的额外权限 - 如果账户同时被
SET PASSWORD EXPIRED或FAILED_LOGIN_ATTEMPTS限制,解锁只解决“锁定”问题,其他限制仍存在 - MySQL 8.0.29+ 支持在一条语句中组合操作,例如:
ALTER USER 'x'@'%' ACCOUNT UNLOCK PASSWORD EXPIRE DEFAULT;
替代方案:低版本 MySQL(5.7 / 8.0.11-)怎么禁用异常账户?
没有 ACCOUNT LOCK,就只能靠“让密码失效”来实现等效禁用。
推荐做法是把密码设为空字符串并禁用密码验证(MySQL 5.7+):
ALTER USER 'suspicious'@'%' IDENTIFIED WITH mysql_native_password BY '';
但这有风险:空密码可能被策略拒绝,或触发安全插件拦截。更稳妥的是用随机不可猜字符串:
ALTER USER 'suspicious'@'%' IDENTIFIED BY 'xk3!qL9#vN2$';
- 不要删用户(
DROP USER),避免权限残留或应用配置未同步导致故障 - 不要只改
mysql.user表字段(如password_expired),MySQL 不保证运行时一致性 - 修改后务必执行
FLUSH PRIVILEGES;—— 虽然ALTER USER通常自动刷新,但某些部署(如 ProxySQL 后置)可能需要显式刷新
账户锁定看似简单,但版本兼容性、权限粒度和副作用(比如影响监控账号或备份脚本)常被忽略。上线前最好在同版本测试实例上走一遍完整流程。











