mysql 8.0.19+密码重用策略必须同时设置非零的password_history和password_reuse_interval才生效,缺一即静默失效;二者需配合caching_sha2_password插件与validate_password(strong模式)组件,并通过alter user显式声明用户级策略或set persist配置全局值。

password_history 和 password_reuse_interval 必须同时设非零值
只改其中一个变量,策略完全不生效——不是“效果打折”,而是压根不校验。MySQL 8.0.19+ 的密码重用检查是双条件绑定触发:新密码必须同时避开「最近 N 次」和「M 天内」两条线,任一为 0(默认值)即静默失效。
常见错误现象:ERROR 3753 (HY000): The 'password_reuse_interval' option is not supported for accounts without a password history policy,就是典型缺 password_history 的报错。
-
SET PERSIST password_history = 5;—— 保留最近 5 次密码哈希 -
SET PERSIST password_reuse_interval = 180;—— 同一密码 180 天内不可重用 - 两个命令都必须执行,且推荐用
SET PERSIST(写入mysqld-auto.cnf,重启不丢) - 验证是否生效:
SELECT @@global.password_history, @@global.password_reuse_interval;,结果必须都是非零整数
用户级策略要显式声明 PASSWORD HISTORY 和 PASSWORD REUSE INTERVAL
全局变量只影响后续新建用户,对已有用户无效。哪怕你设了全局 password_history = 5,老用户照样能循环用旧密码,除非你单独给ta加策略。
关键点:两个关键词必须在同一条 ALTER USER 语句里出现,缺一不可。
- 正确写法:
ALTER USER 'alice'@'%' PASSWORD HISTORY 5 PASSWORD REUSE INTERVAL 180 DAY; - 错误写法:
ALTER USER 'alice'@'%' PASSWORD HISTORY 5;(没带时间限制 → 不生效) - 错误写法:
ALTER USER 'alice'@'%' PASSWORD REUSE INTERVAL 180 DAY;(没带次数限制 → 报错ERROR 3753) - 查是否生效:
SELECT User, Host, password_reuse_history, password_reuse_interval FROM mysql.user WHERE User = 'alice';,字段有值才表示绑定成功
caching_sha2_password 插件和 validate_password 组件缺一不可
这两个参数依赖底层机制:认证插件负责存哈希,验证组件负责比对逻辑。任一缺失,设置就形同虚设,且通常不报错,只默默跳过校验。
- 确认插件:
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 'newpass'; - 确认 validate_password 已安装:
SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME = 'validate_password'; - 启用 STRONG 策略:
SET GLOBAL validate_password.policy = STRONG;(MEDIUM 或 LOW 模式下password_history不生效) - 注意:
validate_password在 STRONG 模式下还要求配置词典文件,否则设密码会失败并报错Plugin 'validate_password' could not be initialized
哪些操作根本不会触发历史记录
很多看似“改密码”的操作,其实绕过了整个机制。真正写入 mysql.password_history 表、触发校验的路径非常有限。
-
ALTER USER 'u'@'h' IDENTIFIED BY 'xxx';✅(唯一可靠路径) -
SET PASSWORD = 'xxx';❌(已弃用,不写历史、不校验) - phpMyAdmin 图形界面“修改密码” ❌(底层调用
SET PASSWORD) -
GRANT ... IDENTIFIED BY 'xxx';❌(不触发校验) - root 直接
UPDATE mysql.user SET authentication_string = ...❌(手动改表,历史表不更新) - 空密码不进历史表:
password_reuse_interval对它无效 - 已存在的旧密码不会被自动追加进历史——只有第一次用
ALTER USER ... IDENTIFIED BY改密后,旧密码才正式入档
最易被忽略的是:策略生效后,已登录的会话不受影响,必须退出重连才能触发新校验;mysql.password_history 表是只读的,不能删、不能清空、不能手动插入,只能等记录自然过期或删用户。











