mysql本身不支持输错密码自动锁定,所谓“锁定”实为密码过期后强制重置(error 1820);需先启用validate_password插件/组件,再配置复杂度与default_password_lifetime过期策略,且仅8.0+原生支持password expire语法。

MySQL 本身不支持“自动锁定账号”(比如连续输错5次密码就锁30分钟),所谓“锁定”实际是密码过期后用户无法执行任何语句,必须重置密码才能继续操作——这是唯一接近“锁定”的原生行为。密码复杂度和过期策略可以配置,但需严格区分版本、启用方式和生效边界。
validate_password 插件/组件是否已加载
所有后续配置的前提:插件或组件必须处于 ACTIVE 状态,否则 SET GLOBAL validate_password.length 等设置完全静默失效。
- MySQL 5.7:查
SELECT * FROM information_schema.plugins WHERE plugin_name = 'validate_password';,若无结果,运行INSTALL PLUGIN validate_password SONAME 'validate_password.so'; - MySQL 8.0.17+:优先查组件表
SELECT * FROM mysql.component WHERE component_urn = 'file://component_validate_password';,若为空,执行INSTALL COMPONENT 'file://component_validate_password'; - 常见误判:执行
SHOW VARIABLES LIKE 'validate_password%';返回空或全是默认值,基本说明插件/组件根本没加载 - 配置文件中写错加载方式会导致重启后失效:5.7 要在
my.cnf的[mysqld]段加plugin-load-add=validate_password.so和validate_password=FORCE_PLUS_PERMANENT;8.0.17+ 推荐用组件,避免硬写SONAME 'validate_password.so'(新版可能已移除该文件)
密码复杂度参数怎么设才真正起效
参数名在 SQL 命令和配置文件中格式不同,写错一个字母就等于没配。
- SQL 中用下划线分隔:
SET GLOBAL validate_password.policy = 1;、SET GLOBAL validate_password.length = 12; -
my.cnf中必须用小写+无下划线:validate_password_policy = 1、validate_password_length = 12(注意不是validate_password.policy) -
STRONG(值为 2)策略依赖字典文件,若未设置validate_password_dictionary_file,实际效果等同于MEDIUM - 最小长度受其他参数约束:
validate_password_length必须 ≥validate_password_number_count+validate_password_special_char_count+ 2 ×validate_password_mixed_case_count,否则 SET 会报错 - 策略只对
CREATE USER和ALTER USER ... IDENTIFIED BY生效,不校验 root 初始密码或SET PASSWORD(8.0.14+ 已弃用该语句)
密码过期策略的三种设置方式与陷阱
MySQL 8.0+ 才支持原生密码过期,低于 8.0 的版本没有 PASSWORD EXPIRE 语法,强行改 mysql.user 表属于高风险操作。
- 全局默认:在
my.cnf中写default_password_lifetime = 90,或执行SET PERSIST default_password_lifetime = 90;(推荐,无需重启) - 单个用户立即过期:
ALTER USER 'app'@'%' PASSWORD EXPIRE;,下次登录报ERROR 1820,只能用ALTER USER ... IDENTIFIED BY重置 - 单个用户指定周期:
ALTER USER 'admin'@'localhost' PASSWORD EXPIRE INTERVAL 60 DAY;,注意不是EXPIRE AFTER 60 - 永不过期写法是
PASSWORD EXPIRE NEVER或default_password_lifetime = 0,别写成NULL或留空 - 过期状态不能只看
password_expired = 'Y'字段——它只表示被显式设为过期;真正超期要靠TIMESTAMPADD(DAY, @@default_password_lifetime, password_last_changed)计算
为什么用户改了密码还是登不上
这不是策略没生效,而是 MySQL 对“过期后首次登录”的限制非常严格:用户连接成功,但一执行任何语句(哪怕只是 SELECT 1;)就报 ERROR 1820,且不提供交互式重置入口。
- 客户端(如 MySQL Workbench、Navicat)可能把错误吞掉或显示不全,建议用命令行复现:
mysql -uapp -p -e "SELECT 1;" - 应用程序必须捕获
ERROR 1820并触发密码重置流程,不能依赖数据库自动跳转或提示 - root 用户首次登录后强制改密(
ERROR 1820)也走同一套逻辑,但仅限首次,之后不受default_password_lifetime影响 - 没有“输错N次锁定”机制,也没有“临时解锁”命令;所谓“锁定”本质就是密码过期后的强制重置流程











