MySQL 8.0.12+ 才真正支持 ACCOUNT LOCK,低版本执行直接报错 ERROR 1064;需先查版本 SELECT VERSION(),锁定需 SYSTEM_USER 权限、不能自锁、必须指定完整 host,且仅阻断新连接。

MySQL 8.0.12+ 才真正支持 ACCOUNT LOCK,低版本执行直接报错 ERROR 1064 (42000),不是语法写错了,是压根不认这个关键字。
确认是否能用 ACCOUNT LOCK
先查版本:SELECT VERSION();。只要低于 8.0.12(比如 8.0.11 或所有 5.7),就别试 ACCOUNT LOCK——它不会生效,只会返回语法错误。
- 执行
ALTER USER 'u'@'%' ACCOUNT LOCK;报ERROR 1064?说明版本不够 - 报
ERROR 1227 (42000)?权限不足,不是版本问题 - 成功执行但登录仍正常?检查是否用了已存在的连接(锁定只拦新连接)
锁定账户必须满足的三个硬条件
缺一不可,否则命令看似成功,实则无效或被拒绝:
- 操作者必须有
SYSTEM_USER权限:GRANT SYSTEM_USER ON *.* TO 'dba'@'%'; - 不能对当前登录账户自己执行锁定(
ERROR 3118会循环触发) - 目标账户需明确指定
host段:若存在'baduser'@'localhost'和'baduser'@'%'两条记录,得分别锁两次
推荐加 IF EXISTS 防误报:ALTER USER IF EXISTS 'baduser'@'%' ACCOUNT LOCK;
锁定后验证与常见失效场景
别信 phpMyAdmin 界面——它根本不读取也不显示 account_locked 字段,界面里永远看不到“已锁定”状态。
- 真锁定:运行
SELECT User, Host, account_locked FROM mysql.user WHERE User = 'baduser';,结果中account_locked列为Y - 新连接会立即失败,报错
ERROR 3118 (HY000): Access denied for user 'baduser'@'%' (account is locked) - 已存在的连接不受影响(长连接、连接池里的连接还能继续干活)
- 手动
UPDATE mysql.user SET account_locked = 'Y'不生效——没刷新权限缓存,也绕过校验逻辑
解锁时最容易手滑的两个地方
语法看着简单,但错一个空格或字母就白忙:
-
ACCOUNT UNLOCK中间必须有空格,写成ACCOUNTUNLOCK或ACCOUNT UNLOK都报ERROR 1064 - 解锁不需要
SYSTEM_USER权限以外的额外权限,但如果你用的是普通用户且没被显式授权,仍可能因权限不足失败 - 如果账户同时被
PASSWORD EXPIRE或FAILED_LOGIN_ATTEMPTS限制,ACCOUNT UNLOCK只解“锁”,其他限制还在
复杂点在于:账户锁定是认证阶段拦截,而密码过期、登录失败次数限制是认证后才检查——它们可以共存,但作用位置不同,排查时容易漏掉一层。


















