mysql 8.0密码过期策略仅响应alter user触发的元数据变更,default_password_lifetime只影响新用户;老用户必须逐个执行alter user显式设置,如password expire interval 90 day,否则永不生效。

升级到 MySQL 8.0 后,密码过期策略不是“变严格了”,而是底层逻辑变了:它从“靠改系统表或 SET PASSWORD 猜测生效”变成“只认 ALTER USER 的显式元数据变更”。不调整操作方式,99% 的旧脚本和配置都会失效。
default_password_lifetime 只影响新用户,老用户一个都不管
升级后执行 SET PERSIST default_password_lifetime = 90 或在 my.cnf 里加 default_password_lifetime = 90,只会让后续 CREATE USER 的账号默认 90 天过期。所有已有用户(包括 'root'@'localhost'、'app'@'%')完全不受影响。
- 查当前值必须用
SELECT @@global.default_password_lifetime;,返回0表示永不过期,NULL等同于0 - 误以为设了这个参数就“全站生效”,是线上漏配的最常见原因
-
SET PASSWORD FOR 'u'@'h' = 'xxx'在 8.0.19+ 已弃用,且不更新password_last_changed字段,倒计时不会重置
ALTER USER 是唯一真正生效的方式
MySQL 8.0 的过期逻辑只响应 ALTER USER 触发的元数据变更,包括 password_last_changed 时间戳和内部策略标记。直接 UPDATE mysql.user 改 password_expired 字段完全无效,哪怕你有 SUPER 权限。
- 让账号 90 天后强制改密:
ALTER USER 'root'@'localhost' PASSWORD EXPIRE INTERVAL 90 DAY; - 立即过期(适合临时回收权限):
ALTER USER 'dev'@'localhost' PASSWORD EXPIRE; - 显式禁用(慎用):
ALTER USER 'app_rw'@'10.%.%.%' PASSWORD EXPIRE NEVER; -
'root'@'localhost'和'root'@'%'是两个独立账户,host 必须完全匹配,否则报错ERROR 1396 (HY000)
密码过期后用户还能登录,但几乎不能干任何事
过期不是连接失败,而是首次执行非 SET 类语句时才拦截,错误明确但容易被客户端忽略:
- 登录后执行
SELECT 1;或SHOW TABLES;会立刻报:ERROR 1820 (HY000): You must reset your password using ALTER USER statement before executing this statement. - 允许执行的语句极少:
SET类命令、SELECT 1(仅限无表查询)、SELECT VERSION()等极简语句 - 重置必须用
ALTER USER CURRENT_USER() IDENTIFIED BY 'newpass';,SET PASSWORD不再合法 - 没有原生“过期提醒”,只能靠外部脚本定期查
password_last_changed和@@default_password_lifetime计算到期时间
真正落地策略时,最容易被跳过的一步是:没对存量账号逐个执行 ALTER USER。别信“重启 MySQL 就自动同步”,也别信“改完配置文件就万事大吉”——8.0 的过期机制是账户级的、显式的、不可绕过的,漏掉一个关键账号,就可能在某天凌晨触发 ERROR 1820 导致服务中断。











