MySQL 8.0.19+ 通过 password_history 和 password_reuse_interval 实现密码重用限制,需配合 caching_sha2_password 插件及 ALTER USER 命令生效,手动更新 user 表或跳过验证将不记录历史。

MySQL 8.0+ 如何启用 password_history 策略
MySQL 原生支持密码重用限制,但仅限 8.0.19 及以上版本,且必须配合全局变量 password_history 和用户级属性共同生效。它不是“开个开关就管用”,而是依赖账户的密码验证插件和显式配置。
实操建议:
- 确认 MySQL 版本:
SELECT VERSION();,低于 8.0.19 的版本不支持该功能,强行设置会报错Unknown system variable 'password_history' - 确保默认认证插件是
caching_sha2_password(8.0 默认),mysql_native_password不支持该策略 - 全局启用(影响后续新建用户):
SET PERSIST password_history = 5;(保留最近 5 次密码) - 对已有用户单独设置更可靠:
ALTER USER 'u1'@'%' PASSWORD HISTORY 5;
为什么设置了 password_history 却没生效
最常见原因是密码变更未触发历史记录写入——MySQL 只在使用 ALTER USER ... IDENTIFIED BY 或 SET PASSWORD(配合当前用户上下文)时才存档旧密码哈希;直接 UPDATE mysql.user 表或跳过密码验证流程(如用 --skip-grant-tables 启动)不会记录。
容易踩的坑:
- 用
UPDATE mysql.user SET authentication_string = ...手动改密码 →password_history完全不感知 - 执行
SET PASSWORD但未指定用户(如SET PASSWORD = 'xxx';)→ 默认修改当前用户,但若当前连接是 root 且 host 匹配不精确,可能改错账户 - 客户端工具(如某些 GUI)底层调用的是旧协议或绕过权限系统 → 历史记录丢失
password_reuse_interval 和 password_history 的区别与配合
这两个参数常被混淆,但作用完全不同:password_history 控制“多少次内不可重复”,password_reuse_interval 控制“多少天内不可重复”。二者可同时启用,满足任一条件即拒绝设为旧密码。
典型使用场景:
- 审计要求“近 6 个月不得重用旧密码” → 设
SET PERSIST password_reuse_interval = 180; - 同时要求“最近 10 次密码不得重复” → 设
SET PERSIST password_history = 10; - 若某用户上次密码是 200 天前设的,但属于最近第 3 次 →
password_history拦截,password_reuse_interval不生效
检查密码历史是否真正在工作
不能只看变量值,得验证行为。MySQL 把历史密码哈希存在 mysql.password_history 表里(8.0.23+),但该表默认不可见,需用特定权限查询。
实操验证步骤:
- 先用
ALTER USER 'test'@'localhost' IDENTIFIED BY 'p1';设一个密码 - 再设一次:
ALTER USER 'test'@'localhost' IDENTIFIED BY 'p2'; - 再尝试设回
p1:ALTER USER 'test'@'localhost' IDENTIFIED BY 'p1';→ 应报错ERROR 3031 (HY000): Cannot use the password from the last 5 passwords - 想查记录?需有
SELECT权限在mysql库:SELECT * FROM mysql.password_history WHERE userhost = 'test@localhost';
注意:该表结构受内部版本控制,字段名(如 password_timestamp)可能随小版本变化,别写死解析逻辑。











