必须用高权限账号执行alter user解锁,仅输对密码无法登录;账户锁定、密码过期、认证插件不兼容常共存但错误提示只暴露一个,error 3118明确提示“account is locked”才是真锁定,需用select查account_locked和password_expired字段确认状态,并执行alter user 'root'@'localhost' identified by '新密码' account unlock同步处理锁定与过期,主机名必须严格匹配,且需根据客户端兼容性指定identified with mysql_native_password。

必须用高权限账号执行 ALTER USER 解锁,仅输对密码无法登录;账户锁定、密码过期、认证插件不兼容这三项常共存,但错误提示只暴露一个。
确认账号真被锁(不是密码错或服务没起)
报错 ERROR 3118 (HY000): Access denied for user 'root'@'localhost' (account is locked) 是明确信号;如果只报 Access denied 但没提 “account is locked”,可能是 caching_sha2_password 插件不兼容或 password_expired = 'Y'。
- 用已有高权限账号登录后查状态:
SELECT User, Host, account_locked, password_expired, plugin FROM mysql.user WHERE User = 'root'; -
account_locked = 'Y'才是真锁定;password_expired = 'Y'会阻止首次登录;plugin是caching_sha2_password则老客户端可能连不上 - 注意:
FLUSH PRIVILEGES对解锁完全无效,它只重载权限表,不改变运行时锁定状态
用 ALTER USER 一步解锁并重置密码
只执行 ACCOUNT UNLOCK 不够——若密码已过期,解锁后首次登录仍会被强制改密,而被锁用户根本连不进去。必须同步重置密码。
- 正确写法:
ALTER USER 'root'@'localhost' IDENTIFIED BY '新密码' ACCOUNT UNLOCK; - 主机名必须严格匹配,
'root'@'localhost'不能写成'root'@'%',否则报ERROR 1396 (HY000) - 若提示
ERROR 3022 (HY000): Cannot unlock user ... because the password has expired,说明password_expired和account_locked是两个独立开关,得先重置密码再解锁,或合并成一条语句 - 别漏掉
IDENTIFIED WITH mysql_native_password:如果客户端不支持caching_sha2_password(如旧版 Navicat、PHP 7.4),需一并切换插件:ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '新密码' ACCOUNT UNLOCK;
生产环境推荐用 --init-file 启动模式解锁
避免临时开放 --skip-grant-tables 带来的权限绕过风险,--init-file 只在启动时执行指定 SQL,不跳过权限系统。
- 创建文件
/tmp/unlock-root.sql,内容严格两行(注意空格):ALTER USER 'root'@'localhost' ACCOUNT UNLOCK;和ALTER USER 'root'@'%' ACCOUNT UNLOCK; - 确保文件属主为
mysql:sudo chown mysql:mysql /tmp/unlock-root.sql - 停服务:
sudo systemctl stop mysql,再用命令启动:sudo mysqld --user=mysql --init-file=/tmp/unlock-root.sql & - 检查是否成功:
sudo ss -tlnp | grep :3306;验证登录:mysql -u root -p;成功后立刻sudo kill $(pgrep mysqld),再sudo systemctl start mysql - 常见错误:
ACCOUNT UNLOCK写成ACCOUNTUNLOCK或ACCOUNT UNLOK,会报ERROR 1064
解锁后必须验证插件与远程访问兼容性
解锁只是恢复登录资格,不代表能用旧工具连上。MySQL 8.0 默认插件 caching_sha2_password 兼容性差,且 'root'@'localhost' 和 'root'@'%' 是两个独立账号。
- 进库后立刻查:
SELECT User, Host, plugin FROM mysql.user WHERE User = 'root'; - 若需兼容,分别执行:
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '新密码';和ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '新密码'; - 别只修
localhost忘了%,否则换台机器又连不上——这种问题往往要倒回去查两遍日志才定位到 - 最后确认:
account_locked = 'N'且password_expired = 'N'都已生效
最容易被忽略的是:改完插件没重连测试,或者只处理了本地账号却漏掉远程账号;PASSWORD_LOCK_TIME 参数并不触发自动解锁,所谓“15分钟后自动解”是外部风控逻辑,MySQL 本身不实现。











