MySQL 8.0+ 默认不启用密码过期,需显式设置PASSWORD EXPIRE或配置default_password_lifetime;用户过期后必须用ALTER USER重置密码才能操作,连接池需配套轮转机制。

MySQL 8.0+ 密码过期策略怎么开启
MySQL 8.0 起默认不启用密码过期,必须显式设置 password_expired 或使用 ALTER USER 命令触发。直接改系统表或绕过认证机制无效,且可能破坏账户状态一致性。
-
CREATE USER 'u1'@'localhost' PASSWORD EXPIRE;—— 创建时即过期,首次登录必须改密 -
ALTER USER 'u1'@'localhost' PASSWORD EXPIRE INTERVAL 90 DAY;—— 90 天后自动过期 -
ALTER USER 'u1'@'localhost' PASSWORD EXPIRE NEVER;—— 取消过期(注意:不是PASSWORD EXPIRE DEFAULT) - 全局策略由
default_password_lifetime系统变量控制,默认值为 0(永不过期),设为 60 表示所有新用户默认 60 天过期
用户登录时提示“Your password has expired”怎么办
这是 MySQL 服务端在握手阶段返回的明确错误,客户端(如 mysql CLI、JDBC、Python pymysql)无法跳过。必须重置密码才能继续,且不能用旧密码做任何操作(包括 SELECT)。
- CLI 登录后会进入“沙盒模式”,只允许执行
SET PASSWORD或ALTER USER,其他语句报错ERROR 1820 (HY000): You must reset your password using ALTER USER statement before executing this statement. - 正确重置方式:
ALTER USER 'u1'@'localhost' IDENTIFIED BY 'NewPass123!';
- JDBC 连接需加参数
&allowPublicKeyRetrieval=true&serverTimezone=UTC(仅限测试环境),否则可能卡在 RSA 密钥交换阶段,和过期无关但常被误判
如何批量检查哪些用户密码已过期
查 mysql.user 表的 password_expired 字段是唯一可靠方式。注意该字段是字符串('Y' / 'N'),不是布尔值;且 MySQL 5.7 不支持该字段,升级前勿依赖。
- 查看所有过期用户:
SELECT user, host, password_expired FROM mysql.user WHERE password_expired = 'Y';
- 结合
password_last_changed手动判断是否超期(需与default_password_lifetime对齐):SELECT user, host, password_last_changed, DATE_ADD(password_last_changed, INTERVAL @@default_password_lifetime DAY) AS expires_at FROM mysql.user WHERE @@default_password_lifetime > 0 AND password_last_changed IS NOT NULL; - 修改前务必
FLUSH PRIVILEGES;,否则变更不生效
应用连接池里密码过期导致连接失败怎么应对
连接池(如 HikariCP、Druid)通常不会主动捕获 ERROR 1820 并触发重连逻辑,而是把异常抛给业务层,最终表现为连接获取超时或初始化失败。
- 避免在生产环境用
PASSWORD EXPIRE配合连接池——除非你有配套的密码轮转 + 配置热更新机制 - 监控建议:定期查询
mysql.user表并告警,而不是等应用报错才发现 - 紧急恢复时,不要 kill 掉所有连接线程,而应优先执行
ALTER USER ... IDENTIFIED BY,MySQL 会自动使旧连接在下次查询时断开并要求重认证
PASSWORD EXPIRE,用户就彻底失去「只读访问权」,哪怕只是想看个 SHOW DATABASES 都会被拦截。










