MySQL 8.0+ 中密码过期策略如何设置
MySQL 8.0 开始默认启用密码过期机制,但新用户不会自动过期——必须显式配置。关键在于
password_expired属性和
password_history/
password_reuse_interval等策略参数,它们不作用于单条
CREATE USER语句,而是依赖全局或账户级的
ALTER USER操作。 新建用户时强制首次登录改密:
CREATE USER 'u1'@'localhost' IDENTIFIED BY 'oldpass' PASSWORD EXPIRE;让已有用户下次登录必须改密:
ALTER USER 'u1'@'localhost' PASSWORD EXPIRE;禁用过期(恢复为永不过期):
ALTER USER 'u1'@'localhost' PASSWORD EXPIRE NEVER;设为 90 天后过期:
ALTER USER 'u1'@'localhost' PASSWORD EXPIRE INTERVAL 90 DAY;
为什么 SET PASSWORD 不再生效,而 ALTER USER 成了唯一方式
MySQL 5.7.6 起弃用
SET PASSWORD语句对密码过期状态的控制能力;8.0 后彻底移除其修改过期属性的功能。直接执行
SET PASSWORD FOR 'u1'@'localhost' = 'xxx'只会重置密码,不会清除过期标记,用户仍会在下次登录时被卡在改密流程。 错误做法(改密但不解锁):
SET PASSWORD FOR 'u1'@'localhost' = 'newpass123';正确做法(重置密码 + 解除过期):
ALTER USER 'u1'@'localhost' IDENTIFIED BY 'newpass123' PASSWORD EXPIRE NEVER;如果只想重置密码并保留过期策略,不加
PASSWORD EXPIRE子句即可
登录时提示 ERROR 1820:You must SET PASSWORD before executing this statement 怎么办
这是 MySQL 强制改密流程触发的典型错误,说明该账户处于
password_expired = 'Y'状态,且当前 session 尚未完成密码更新。此时不能执行任何非密码修改类语句(包括
SELECT、
SHOW DATABASES)。 必须使用
ALTER USER ... IDENTIFIED BY(不是
SET PASSWORD):
ALTER USER USER() IDENTIFIED BY 'new_secure_pass';若已断开连接,需用高权限账号(如 root)代为重置:
ALTER USER 'u1'@'localhost' IDENTIFIED BY 'newpass' PASSWORD EXPIRE NEVER;检查状态可查:
SELECT user, host, password_expired FROM mysql.user WHERE user = 'u1';
全局策略与账户级策略的优先级关系
MySQL 支持两层密码策略:全局系统变量(如
default_password_lifetime)和账户级显式设置。后者永远优先——哪怕全局设为 0(永不过期),只要对某个用户执行了
PASSWORD EXPIRE,该用户仍会过期。 查看全局默认生命周期:
SELECT @@default_password_lifetime;(0 表示永不过期) 修改全局策略(影响后续新建用户,不影响已有用户):
SET PERSIST default_password_lifetime = 180;账户级设置一旦存在,就覆盖全局值;用
PASSWORD EXPIRE NEVER可显式解除继承
password_history和
password_reuse_interval同样遵循账户 > 全局的优先级,且仅在用户改密时校验(不阻止登录) 实际操作中容易忽略的是:密码过期状态不随密码重置自动清除,也不受全局策略动态调整影响。每次变更都要明确指定
PASSWORD EXPIRE子句,否则策略残留会导致后续维护混乱。
