必须分两步配:先设过期时间,再设重用限制;只做一步等于没做。default_password_lifetime只影响新建用户,老用户须逐个执行ALTER USER ... PASSWORD EXPIRE INTERVAL;password_history和password_reuse_interval必须同时用SET PERSIST设置且非零,且依赖caching_sha2_password和validate_password插件生效,仅对ALTER USER ... IDENTIFIED BY触发校验。

必须分两步配:先设过期时间,再设重用限制;只做一步等于没做。
设置密码过期时间(default_password_lifetime 和 ALTER USER ... PASSWORD EXPIRE INTERVAL)
MySQL 不会自动让所有用户 90 天后过期——default_password_lifetime 只影响新建用户,老用户完全不受影响。
- 全局默认值只对后续
CREATE USER生效:执行SET PERSIST default_password_lifetime = 90;后,新用户默认 90 天过期 - 已有用户(包括
root)必须逐个处理:ALTER USER 'app'@'%' PASSWORD EXPIRE INTERVAL 90 DAY; - 查当前状态用:
SELECT user, host, password_last_changed, password_lifetime FROM mysql.user WHERE user = 'app';,其中password_lifetime为 90 才算生效 - 误用
SET PASSWORD无效:它不更新password_last_changed,也不触发过期逻辑,只会让你以为改了密码其实没刷新时间戳
启用密码重用限制(password_history 和 password_reuse_interval 必须同时设)
这两个变量是“与”关系:任一为 0 或未设置,校验直接跳过,不会报错,但旧密码随便重用。
- 必须都用
SET PERSIST设置(推荐):SET PERSIST password_history = 5;和SET PERSIST password_reuse_interval = 365; - 验证是否真生效:
SELECT @@global.password_history, @@global.password_reuse_interval;,两个都得是非零整数 - 已有用户需显式绑定策略:
ALTER USER 'alice'@'%' PASSWORD HISTORY 5 PASSWORD REUSE INTERVAL 365 DAY;—— 缺任何一个关键词都会失败或静默忽略 - 常见报错
ERROR 3753 (HY000): The 'password_reuse_interval' option is not supported...就是因为漏了PASSWORD HISTORY
依赖组件必须就位(caching_sha2_password + validate_password)
没有这两个插件,前面所有设置全是摆设,而且 MySQL 通常不报错,只默默跳过校验。
- 确认用户认证插件:
SELECT user, host, plugin FROM mysql.user WHERE user = 'alice';,结果必须是caching_sha2_password(mysql_native_password不支持历史记录) - 切换插件:
ALTER USER 'alice'@'%' IDENTIFIED WITH caching_sha2_password BY 'xxx'; - 检查
validate_password是否加载:SELECT * FROM information_schema.PLUGINS WHERE PLUGIN_NAME = 'validate_password';,没结果就得手动安装:INSTALL COMPONENT 'file://component_validate_password'; - 如果只启用了插件但没开 STRONG 模式,
password_history可能仍不生效——建议设validate_password.policy = STRONG;
为什么改完还是能重用旧密码?关键排查点
最常被忽略的是:策略只对 ALTER USER ... IDENTIFIED BY 生效,且从第一次执行该语句起才开始记录历史。
- 用
SET PASSWORD改密 → 不写入mysql.password_history表,也不触发校验 - 用户之前从未用
ALTER USER改过密 →mysql.password_history表为空,第一次设策略时无历史可比,重用旧密码也不会拦 - 版本低于 8.0.19 →
password_reuse_interval不可用,查SELECT VERSION();确认 - 用户 host 不匹配:设的是
'user'@'localhost',但登录用的是'user'@'127.0.0.1',这是两个账户,策略不共享
真正起作用的不是参数本身,而是它们在 ALTER USER 执行瞬间触发的一整套链路:插件存哈希、组件比对、表记录写入。任何一环断开,策略就失效,而且往往悄无声息。


















