如何迅速锁定MySQL中疑似泄露的账户,执行ALTER USER命令?
- 内容介绍
- 文章标签
- 相关推荐
本文共计784个文字,预计阅读时间需要4分钟。
立即生效,无需等待、无需刷新权限、不依赖插件——只需MySQL版本≥5.7.6,执行以下命令即可:
确认账号存在且版本支持
执行前先查两件事:
- 用
SELECT VERSION();确认版本 ≥ 5.7.6;低于这个版本会报ERROR 1064 (42000),得换方案(比如临时清空密码或改认证插件) - 用
SELECT User, Host FROM mysql.user WHERE User = 'xxx';核对账号的Host值——'u1'@'%'和'u1'@'192.168.1.100'是两个不同账号,锁错 host 就白忙
锁定语句必须带完整 host,不能省略
常见错误是只写用户名,比如 ALTER USER 'u1' ACCOUNT LOCK;,这会直接报 ERROR 1396 (HY000)。MySQL 要求显式指定 host,哪怕你记得它在 mysql.user 表里是 '%' 或 'localhost':
- 正确写法:
ALTER USER 'u1'@'%' ACCOUNT LOCK; - 正确写法:
ALTER USER 'u1'@'localhost' ACCOUNT LOCK; - 错误写法:
ALTER USER 'u1' ACCOUNT LOCK;(语法不通过)
执行后立刻生效,不需要 FLUSH PRIVILEGES; —— 这个状态是运行时实时读取的,不是缓存项。
锁定后仍能登录?大概率是 host 不匹配或连接复用
如果执行完还能连上,别急着重试,先排查:
- 客户端实际用的 host 是否和锁定语句中的一致?比如你锁了
'u1'@'192.168.1.%',但应用连的是'u1'@'192.168.1.100',而 MySQL 没配通配匹配规则,就可能漏掉 - 当前连接是旧会话:
ACCOUNT LOCK只拦新连接,已存在的连接不受影响,用户仍可执行命令直到断开 - 账号有
SUPER或SYSTEM_USER权限,在某些老客户端或配置下可能绕过锁定(极少见,但生产环境建议验证)
验证是否真锁住:用另一个终端尝试新连接,会收到明确错误 ERROR 3956 (HY000): Account u1@localhost is locked 或 ERROR 3118 (HY000)。
解锁时遇到 ERROR 3022?说明密码也过期了
执行 ALTER USER 'u1'@'localhost' ACCOUNT UNLOCK; 报 ERROR 3022 (HY000): Cannot unlock user ... because the password has expired,这不是锁的问题,是 password_expired 和 account_locked 两个开关独立存在:
- 先查状态:
SELECT User, Host, account_locked, password_expired FROM mysql.user WHERE User = 'u1'; - 如果
password_expired = 'Y',得一起处理:ALTER USER 'u1'@'localhost' IDENTIFIED BY 'newpass' PASSWORD EXPIRE NEVER ACCOUNT UNLOCK; - MySQL 8.0 默认用
caching_sha2_password插件,若客户端太老(如 pymysql
真正要命的点是:锁定只是拦登录,不杀会话;如果攻击者已经连上了,还得手动 KILL CONNECTION 查杀活跃线程,否则权限还在手里。
本文共计784个文字,预计阅读时间需要4分钟。
立即生效,无需等待、无需刷新权限、不依赖插件——只需MySQL版本≥5.7.6,执行以下命令即可:
确认账号存在且版本支持
执行前先查两件事:
- 用
SELECT VERSION();确认版本 ≥ 5.7.6;低于这个版本会报ERROR 1064 (42000),得换方案(比如临时清空密码或改认证插件) - 用
SELECT User, Host FROM mysql.user WHERE User = 'xxx';核对账号的Host值——'u1'@'%'和'u1'@'192.168.1.100'是两个不同账号,锁错 host 就白忙
锁定语句必须带完整 host,不能省略
常见错误是只写用户名,比如 ALTER USER 'u1' ACCOUNT LOCK;,这会直接报 ERROR 1396 (HY000)。MySQL 要求显式指定 host,哪怕你记得它在 mysql.user 表里是 '%' 或 'localhost':
- 正确写法:
ALTER USER 'u1'@'%' ACCOUNT LOCK; - 正确写法:
ALTER USER 'u1'@'localhost' ACCOUNT LOCK; - 错误写法:
ALTER USER 'u1' ACCOUNT LOCK;(语法不通过)
执行后立刻生效,不需要 FLUSH PRIVILEGES; —— 这个状态是运行时实时读取的,不是缓存项。
锁定后仍能登录?大概率是 host 不匹配或连接复用
如果执行完还能连上,别急着重试,先排查:
- 客户端实际用的 host 是否和锁定语句中的一致?比如你锁了
'u1'@'192.168.1.%',但应用连的是'u1'@'192.168.1.100',而 MySQL 没配通配匹配规则,就可能漏掉 - 当前连接是旧会话:
ACCOUNT LOCK只拦新连接,已存在的连接不受影响,用户仍可执行命令直到断开 - 账号有
SUPER或SYSTEM_USER权限,在某些老客户端或配置下可能绕过锁定(极少见,但生产环境建议验证)
验证是否真锁住:用另一个终端尝试新连接,会收到明确错误 ERROR 3956 (HY000): Account u1@localhost is locked 或 ERROR 3118 (HY000)。
解锁时遇到 ERROR 3022?说明密码也过期了
执行 ALTER USER 'u1'@'localhost' ACCOUNT UNLOCK; 报 ERROR 3022 (HY000): Cannot unlock user ... because the password has expired,这不是锁的问题,是 password_expired 和 account_locked 两个开关独立存在:
- 先查状态:
SELECT User, Host, account_locked, password_expired FROM mysql.user WHERE User = 'u1'; - 如果
password_expired = 'Y',得一起处理:ALTER USER 'u1'@'localhost' IDENTIFIED BY 'newpass' PASSWORD EXPIRE NEVER ACCOUNT UNLOCK; - MySQL 8.0 默认用
caching_sha2_password插件,若客户端太老(如 pymysql
真正要命的点是:锁定只是拦登录,不杀会话;如果攻击者已经连上了,还得手动 KILL CONNECTION 查杀活跃线程,否则权限还在手里。

