ALTER USER是唯一能真正解除密码过期状态的命令,它同时更新authentication_string、password_last_changed和password_expired='N';SET PASSWORD或UPDATE mysql.user仅改密不解除过期标志,执行后仍报ERROR 1820。

ALTER USER 是唯一能真正解除密码过期状态的命令
遇到 ERROR 1820 (HY000): You must reset your password using ALTER USER statement before executing this statement,说明用户密码已过期。此时即使输入正确密码登录成功,第一条 SQL 也会失败——这不是权限问题,是 MySQL 的强制策略。
SET PASSWORD 或直接 UPDATE mysql.user 都不能清除 password_expired 标志位,只会改密不“解绑”过期状态。只有 ALTER USER 'u'@'h' IDENTIFIED BY 'newpass' 才会同时更新 authentication_string、password_last_changed 和 password_expired='N',才算真正重置。
- 必须指定完整 host:
'root'@'localhost'≠'root'@'127.0.0.1'≠'root'@'%' - 执行后无需
FLUSH PRIVILEGES,该语句自动生效 - 如果提示
ERROR 1819,说明启用了validate_password插件,新密码需含大小写字母+数字+符号且 ≥8 位
设置密码永不过期的两种等效方式
修改完密码后,还需显式关闭该用户的过期开关,否则下次到期仍会触发 1820 错误。推荐用以下任一方式:
ALTER USER 'root'@'localhost' PASSWORD EXPIRE NEVER;-
ALTER USER 'root'@'localhost' IDENTIFIED BY '新密码' PASSWORD EXPIRE NEVER;(一步完成改密 + 解过期)
注意:不能只执行 SET PASSWORD 再补一句 ALTER USER ... PASSWORD EXPIRE NEVER,因为前者不会清除 password_expired='Y',后者单独执行又要求当前密码未过期——形成死锁。必须用 ALTER USER ... IDENTIFIED BY 开头才能破局。
全局禁用密码过期(适用于所有新用户)
如果希望后续创建的所有用户默认永不过期,需修改全局策略:
- 临时生效(重启失效):
SET GLOBAL default_password_lifetime = 0; - 永久生效:在
my.cnf的[mysqld]段落下添加default_password_lifetime=0,然后重启 mysqld
该设置不影响已有用户的 password_expired 状态,只影响新用户创建时的默认行为。已有用户仍需单独执行 ALTER USER ... PASSWORD EXPIRE NEVER。
root 密码过期且无法登录时的兜底方案
当 root 密码过期且无其他高权限账号可用时,常规登录路径完全失效。唯一可行方案是绕过权限系统启动 mysqld:
- 停服务:
sudo systemctl stop mysqld(Linux)或结束mysqld.exe进程(Windows) - 跳过权限启动:
mysqld --skip-grant-tables --skip-networking & - 本地免密连接:
mysql -u root(仅限 socket,禁止 DDL) - 立即执行:
ALTER USER 'root'@'localhost' IDENTIFIED BY '新密码' PASSWORD EXPIRE NEVER; - 退出,手动杀掉 mysqld 进程,再正常启动服务
关键点在于:跳过权限模式下,UPDATE mysql.user 不可靠——容易漏掉 password_expired 字段或写错时间戳;必须用 ALTER USER 语句,它内部做了字段联动更新。


















