password_history和password_reuse_interval是mysql 8.0.19+密码重用限制参数:前者指定最多保留n次旧密码(如5),后者限定同一密码不可重用的天数(如365),二者必须同时设置且依赖validate_password插件生效,仅对alter user语句触发校验。

password_history 和 password_reuse_interval 是什么
这两个是 MySQL 8.0+ 的密码重用限制参数,和 default_password_lifetime 配合使用才能真正防住“换汤不换药”——比如用户把密码从 p@ss123 改成 p@ss124 再改回 p@ss123。它们不控制过期时间,只管“能不能重复用旧密码”。password_history = 5 表示最多记住最近 5 次密码,第 6 次重设时不能选这 5 个;password_reuse_interval = 365 表示同一密码 365 天内不准重用,哪怕它没在最近 5 次里。
如何设置并确认生效
必须用 SET PERSIST(推荐)或 SET GLOBAL 设置,且需 SYSTEM_VARIABLES_ADMIN 权限:
-
SET PERSIST password_history = 5;—— 永久写入mysqld-auto.cnf,重启不丢 -
SET PERSIST password_reuse_interval = 365;—— 单位是天,设为 0 表示禁用该限制 - 查当前值:
SELECT @@global.password_history, @@global.password_reuse_interval; - 注意:这两个变量对已存在的旧密码不追溯,只从设置后第一次改密开始生效
为什么改了还是能重用旧密码
常见错误场景和排查点:
- 没启用
validate_password插件/组件:这两个参数依赖密码验证机制,若validate_password未加载,设置会静默失败或无效 - 用户用
SET PASSWORD改密:该语句已被弃用,且不触发历史校验;必须用ALTER USER ... IDENTIFIED BY - 重设密码时用了
PASSWORD REQUIRE CURRENT但没配策略:这个子句本身不启用历史检查,只是要求输入当前密码,真正拦住重用的是password_history和password_reuse_interval - MySQL 版本低于 8.0.19:部分行为支持不完整,建议确认版本:
SELECT VERSION();
和 default_password_lifetime 配合使用的要点
单独设 default_password_lifetime 只解决“不换”,不解决“乱换”。三者要一起开才形成闭环:
- 先设全局过期:
SET PERSIST default_password_lifetime = 90; - 再加重用限制:
SET PERSIST password_history = 5;+SET PERSIST password_reuse_interval = 365; - 已有用户仍需显式覆盖:
ALTER USER 'app'@'%' PASSWORD EXPIRE INTERVAL 90 DAY;(否则不受default_password_lifetime约束) - 验证是否真起作用:用目标用户登录后执行
ALTER USER USER() IDENTIFIED BY 'oldpass123';,如果之前用过这个密码且在 5 次历史内或 365 天内,就会报ERROR 3031 (HY000): Cannot use previous password
最容易被忽略的是:这三个参数彼此独立生效,缺一不可;而且它们都只对 ALTER USER 触发的密码修改起作用,任何绕过该语句的操作(如直接更新 mysql.user 表)都会让策略失效。











