error 1862 表示密码已过期但可登录,需立即执行 alter user 修改密码;连不上则需跳过权限表启动后改密,并手动 flush privileges;禁用过期策略推荐 alter user ... password expire never。

能连上但执行语句报 ERROR 1862,说明密码已过期;连都连不上,大概率是 root 密码过期且客户端不支持过期密码登录流程 —— 这两种情况处理路径完全不同,不能混用。
ERROR 1862 报错时直接用 ALTER USER 重置密码
你还能用 mysql -u root -p 登录,只是输入密码后一执行任何命令就报 ERROR 1862 (HY000): Your password has expired. To log in you must change it using a client that supports expired passwords.,说明 MySQL 允许你“带过期状态登录”,但强制你立刻改密。
此时不要去碰 user 表或 authentication_string 字段,MySQL 5.7+ 要求必须走 ALTER USER 流程:
- 登录后立即执行:
ALTER USER 'root'@'localhost' IDENTIFIED BY '新密码'; - 如果提示
ERROR 1820 (HY000): You must reset your password using ALTER USER statement before executing this statement,说明你已经进了会话但还没改密,必须先执行上面那条ALTER USER,再执行其他语句 - 不需要
FLUSH PRIVILEGES——ALTER USER自动生效 - 改完立刻验证:
SELECT User, Host, password_expired FROM mysql.user WHERE User = 'root';,确认password_expired是N
连不上 MySQL:必须跳过权限表启动
用 mysql -u root -p 输完密码直接报错退出、根本进不了 MySQL 提示符,说明客户端(比如旧版 MySQL CLI 或某些 GUI 工具)不支持“过期密码登录后强制改密”流程,得绕过验证。
关键点不是“停服务”,而是“以无权限校验方式启动”:
- Linux/macOS:先
sudo systemctl stop mysql(或brew services stop mysql),再运行sudo mysqld_safe --skip-grant-tables --skip-networking &——--skip-networking防止远程未授权访问 - Windows:编辑
my.ini,在[mysqld]下加一行skip-grant-tables,然后重启服务 - 此时直接
mysql -u root(不加-p)就能进,不用输密码 - 进库后先
USE mysql;,再执行:ALTER USER 'root'@'localhost' IDENTIFIED BY '新密码';(推荐)或UPDATE user SET authentication_string = PASSWORD('新密码') WHERE User = 'root' AND Host = 'localhost';(兼容旧习惯,但不如ALTER USER安全) - 必须执行
FLUSH PRIVILEGES;,否则更改不生效 - 改完删掉
my.ini里的skip-grant-tables或杀掉mysqld_safe进程,再正常启服务
禁用密码过期策略要分全局和用户两级
频繁遇到这个问题,说明 default_password_lifetime 没调好。它默认是 0(永不过期)还是 360?得看安装时是否被修改过。别只改配置文件,有些参数必须运行时设才管用。
两种改法效果不同:
- 全局禁用(影响所有新用户):
SET GLOBAL default_password_lifetime = 0;,但该设置重启后失效;要持久化,必须写进my.cnf的[mysqld]段并重启服务 - 单用户永不过期(推荐,更细粒度):
ALTER USER 'root'@'localhost' PASSWORD EXPIRE NEVER;,这条立即生效且永久有效,无需重启 - 查当前值:
SHOW VARIABLES LIKE 'default_password_lifetime';和SELECT User, Host, password_expired, password_last_changed FROM mysql.user WHERE User = 'root';
docker 环境下 root 密码过期容易被忽略的点
用 docker run -e MYSQL_ROOT_PASSWORD=xxx 启的 MySQL 5.7,默认不会设 default_password_lifetime,但如果你挂载了自定义 my.cnf,里面若含 default_password_lifetime = 90,容器内 root 密码照样过期 —— 这个配置优先级高于环境变量。
验证方法很简单:
- 进容器:
docker exec -it mysql5.7 mysql -u root -p - 输密码后如果卡在 ERROR 1862,就说明过期了
- 临时解决:在容器里执行
ALTER USER 'root'@'%' IDENTIFIED BY 'xxx';(注意 host 是%而非localhost,因为 docker 默认绑定 0.0.0.0) - 根治办法:在挂载的
my.cnf中显式写default_password_lifetime = 0,或加ALTER USER ... PASSWORD EXPIRE NEVER到容器初始化脚本里
真正麻烦的不是改密本身,而是忘记检查 password_expired 字段是否真变成 N,以及没意识到 ALTER USER 和 UPDATE user 在权限刷新机制上的差异 —— 前者自动刷,后者必须手动 FLUSH PRIVILEGES。











