MySQL密码强度需启用validate_password插件并显式配置参数:length≥12、mixed_case_count≥1、number_count≥1、special_char_count≥1;8.0+用component_validate_password,MariaDB不支持,且策略仅对新设/修改密码生效。

MySQL 用户密码长度和复杂度怎么设才有效
MySQL 本身不内置密码强度校验,validate_password 插件是唯一靠谱的防线,但默认不启用,启了也不一定生效——常见错误是只装插件没调参数,或者用老版本(5.7.8 之前)根本没这功能。
实操建议:
- 先确认插件已加载:
SHOW PLUGINS;查看validate_password状态,若为DISABLED,执行INSTALL PLUGIN validate_password SONAME 'validate_password.so'; - 关键参数必须显式设置,不能依赖默认值:
SET GLOBAL validate_password.length = 12;、SET GLOBAL validate_password.mixed_case_count = 1;、SET GLOBAL validate_password.number_count = 1;、SET GLOBAL validate_password.special_char_count = 1; - 注意兼容性:MySQL 8.0+ 改用组件机制,插件名变为
component_validate_password,路径和加载方式不同;MariaDB 完全不支持该插件,得靠应用层或 PAM - 密码策略只对新设/修改密码生效,已有弱密码用户不会被强制重置,得手动筛查:
SELECT user, host FROM mysql.user WHERE LENGTH(authentication_string)
ALTER USER 设置密码时为什么报错 ERROR 1819
这是 validate_password 插件拦截的典型错误,不是语法错,而是密码被判定“太简单”。很多人以为加个数字就行,其实插件会逐项检查:长度、大小写、数字、特殊字符、是否含用户名或主机名。
常见踩坑点:
- 用单引号包裹密码时多打了空格:
ALTER USER 'app'@'%' IDENTIFIED BY ' pass123! ';→ 前后空格会被算进长度,但校验时可能被 trim,导致实际校验失败 - 密码含 MySQL 关键字如
password、user,插件会拒绝(即使满足长度) - 在非 root 用户下执行
ALTER USER,但没被授予SYSTEM_USER权限(8.0+ 要求),会报错ERROR 1227,容易误判为密码问题 - 临时绕过策略仅限当前 session:
SET SESSION validate_password.policy = LOW;,但生产环境禁用策略等于开后门,不推荐
密码定期轮换怎么做才不中断业务
MySQL 没有原生密码过期调度,ALTER USER ... PASSWORD EXPIRE 只能设单次过期,不能自动轮换。硬编码在应用配置里改密码,上线就断连,是最常见的翻车现场。
可行路径只有两条:
- 用外部工具驱动:比如 Ansible +
mysql_user模块,配合 cron 定期执行,同时更新应用配置中心(如 Consul/Nacos)和数据库,再触发应用 reload 配置(需应用支持热更) - 走代理层隔离:在应用和 MySQL 之间加 ProxySQL 或 MaxScale,把密码存在其配置中,轮换时只重启代理配置,应用无感
- 绝对避免:直接在应用代码里写死密码、或用 shell 脚本暴力替换配置文件——没原子性,易残留旧密码,且无法审计谁改的
- 注意权限最小化:轮换账号只需
CREATE USER、DROP USER、GRANT OPTION,别给ALL PRIVILEGES,防止误删库
如何验证密码策略真正在起作用
装完插件、设完参数,不代表万事大吉。很多团队跳过验证环节,上线后才发现策略形同虚设——比如插件加载失败但没报错,或参数被配置文件覆盖却没 reload。
必须做的检查项:
- 查运行时值:
SELECT @@validate_password.length, @@validate_password.policy;,确认是刚设的值,不是0或DEFAULT - 模拟弱密码测试:
CREATE USER 'test_weak'@'localhost' IDENTIFIED BY '123456';,应明确报ERROR 1819 - 检查配置文件是否冲突:如果
my.cnf里有validate_password=OFF或参数设为0,启动时会覆盖 SET GLOBAL 的值 - 注意 scope:GLOBAL 参数对已连接会话无效,新连接才生效,验证时务必开新客户端连接测试
最常被忽略的是插件加载时机——mysqld 启动时没加载,后续手动 INSTALL 成功,但配置文件没补上 plugin_load_add = validate_password.so,下次重启就失效。这事没法靠监控告警,只能进机器查进程启动参数或 error log。


















