MySQL不提供密码过期提醒功能,仅强制执行过期策略;通知需由外部系统实现,常用方案为定时脚本扫描mysql.user表并邮件提醒,或应用层主动检查剩余天数后推送告警。

MySQL 本身不提供密码过期前的邮件或系统级提醒通知机制,它只负责强制执行过期策略(如 ALTER USER ... PASSWORD EXPIRE),但不会主动“提醒”用户密码即将过期。
MySQL 密码过期策略本身不包含通知功能
MySQL 的密码过期是纯服务端校验行为:用户登录时,如果密码已过期(password_last_changed + default_password_lifetime 超期),直接拒绝连接并报错 ERROR 1820 (HY000): You must reset your password using ALTER USER statement before executing this statement.。它没有后台任务、钩子或事件能触发外部通知。
- 所有通知必须由外部系统实现,MySQL 不参与
-
default_password_lifetime是全局配置,对新用户生效;已有用户需用ALTER USER ... PASSWORD EXPIRE AFTER N DAYS单独设置 - 查询密码到期时间需手动计算:
SELECT user, host, password_last_changed, DATE_ADD(password_last_changed, INTERVAL @@default_password_lifetime DAY) AS expires_at FROM mysql.user;
用定时脚本扫描 + 邮件通知(最常用可行方案)
在数据库服务器或运维机上部署一个定期运行的脚本(如每天凌晨),查出 expires_at 在未来 7 天内且尚未过期的账号,调用 mail 或 SMTP 工具发提醒。关键点:
- 必须用有
SELECT权限的账号连接 MySQL(建议专用只读账号,权限限定在mysql.user表) - 避免直接暴露 root 密码:用
~/.my.cnf配置文件存凭据,并设chmod 600 - SQL 查询要过滤掉过期账号(
expires_at > NOW())和系统账号(user NOT IN ('mysql.infoschema', 'mysql.session', ...)) - 示例核心查询:
SELECT CONCAT('''', user, '''@''', host, '''') AS account, DATEDIFF(DATE_ADD(password_last_changed, INTERVAL @@default_password_lifetime DAY), NOW()) AS days_left FROM mysql.user WHERE password_last_changed IS NOT NULL AND DATE_ADD(password_last_changed, INTERVAL @@default_password_lifetime DAY) BETWEEN NOW() AND DATE_ADD(NOW(), INTERVAL 7 DAY);
应用层拦截 + 友好提示(面向终端用户)
如果你的应用使用固定数据库账号(比如 Java 应用连 app_user),可以在连接池初始化或每次获取连接前,主动检查该账号状态:
- 执行
SELECT password_last_changed, @@default_password_lifetime获取当前值 - 计算剩余天数,若 ≤ 3 天,在应用日志打 warning,或向管理员企业微信/钉钉机器人推送消息
- 注意:不能依赖
SHOW VARIABLES LIKE 'default_password_lifetime'—— 它只返回全局值,不反映单个用户的PASSWORD EXPIRE AFTER设置 - 更稳妥的做法是查
mysql.user表中该用户的password_last_changed和password_lifetime字段(MySQL 8.0.19+ 支持 per-user lifetime)
真正容易被忽略的是权限与时效性:脚本账号必须有 SELECT 权限且不能被密码过期影响自身;mysql.user 表的 password_last_changed 字段在某些旧版本(如 5.7)里是 NULL,需要先确认是否启用了密码策略(validate_password 插件不是必需条件,但会影响字段写入逻辑)。


















