MySQL 8.0密码过期策略不能仅靠default_password_lifetime参数全局生效,该值默认为0(永不过期),仅影响新用户;已有用户必须用ALTER USER单独设置,如ALTER USER 'root'@'localhost' PASSWORD EXPIRE INTERVAL 90 DAY。

MySQL 8.0 的密码过期策略不能靠“设个参数就全搞定”,default_password_lifetime 只管新用户,默认值是 0(永不过期),改了它,老用户一个都不会受影响——这是最常被当成“已生效”却实际失效的点。
怎么查当前全局密码过期设置是否生效
别翻配置文件、别猜,直接连上 MySQL 执行:
SELECT @@global.default_password_lifetime;
返回 0 表示禁用;返回正整数(如 90)表示新用户默认 90 天后过期。注意:这个值只在你执行过 SET PERSIST 或重启后加载了 my.cnf 才真正代表运行时状态。如果返回 NULL,说明变量未初始化或被重置过,行为等同于 0。
永久启用 90 天策略:推荐用 SET PERSIST 而不是改配置文件
写 my.cnf 需要重启、容易因编码/BOM/段落错位导致 MySQL 启动失败;而 SET PERSIST 会自动写入 mysqld-auto.cnf,安全且无需重启:
-
SET PERSIST default_password_lifetime = 90;—— 新建用户默认 90 天后过期 -
SET PERSIST default_password_lifetime = 0;—— 关闭全局过期(生产环境更稳妥) - 执行需
SYSTEM_VARIABLES_ADMIN权限,普通账号会报错:ERROR 1227 (42501): Access denied - 执行后务必再跑一遍
SELECT @@global.default_password_lifetime;确认读取的是新值,不是缓存
已有用户为什么还是没过期?必须用 ALTER USER 单独处理
default_password_lifetime 对已存在用户完全无效——包括 root。它的作用仅限于 CREATE USER 时未显式指定 PASSWORD EXPIRE 的场景。想让老用户也遵守 90 天策略,只能逐个执行:
ALTER USER 'root'@'localhost' PASSWORD EXPIRE INTERVAL 90 DAY;ALTER USER 'admin'@'%' PASSWORD EXPIRE INTERVAL 90 DAY;- 不支持批量语法,得自己写脚本查
mysql.user表 + 循环执行ALTER USER - 误用
SET PASSWORD FOR 'u'@'h' = 'xxx'完全无效:该语句不更新password_expired字段,也不触发过期逻辑
密码过期后用户还能登录吗?行为和错误提示很关键
能登录,但几乎什么都干不了:
- 首次执行非
SET类语句(比如SELECT 1;、SHOW TABLES;)就会报:ERROR 1820 (HY000): You must reset your password using ALTER USER statement before executing this statement. - 允许执行的语句极少:
SET、UNLOCK TABLES、SELECT(只读)、ALTER USER ... IDENTIFIED BY - 用户自己重置要用:
ALTER USER USER() IDENTIFIED BY 'newpass';;管理员可代为执行:ALTER USER 'user'@'host' IDENTIFIED BY 'newpass'; - 没有交互式提示,客户端可能静默失败,排查时得看错误码而非连接日志
真正落地密码策略,default_password_lifetime 是起点,不是终点;存量账号必须靠 ALTER USER 显式覆盖,漏掉任何一个关键账号(比如备份账户或监控账户),都可能在某次例行巡检时突然失联——这点比参数本身还容易被忽略。



















