MySQL 8.0+ 通过 ALTER USER 设置密码过期时间实现间接权限时效控制,如 PASSWORD EXPIRE INTERVAL 7 DAY;GRANT/REVOKE 无时间维度,权限变更不影响已存在连接。

MySQL 8.0+ 如何给账号设置密码过期时间
MySQL 本身不支持“账号权限的有效生命周期”,但能通过密码过期机制间接实现权限失效——用户密码过期后无法登录,自然无法使用任何权限。ALTER USER 是唯一可靠方式,CREATE USER 仅在建号时生效,后续无法回溯修改。
常见错误是误以为 GRANT 或角色(ROLE)能控制时效,其实它们完全不涉及时间维度。真正起作用的只有密码策略相关字段:password_expired、password_last_changed 和 password_lifetime。
-
ALTER USER 'dev'@'%' PASSWORD EXPIRE INTERVAL 7 DAY:7 天后强制改密 -
ALTER USER 'dev'@'%' PASSWORD EXPIRE DEFAULT:恢复全局策略(由default_password_lifetime决定) -
SET PERSIST default_password_lifetime = 30:设全局默认为 30 天(需有SYSTEM_VARIABLES_ADMIN权限)
注意:PASSWORD EXPIRE NEVER 并非永久有效,而是跳过过期检查——一旦全局策略收紧或手动触发过期,仍会立即生效。
为什么不能靠 GRANT 或 REVOKE 实现“临时权限”
MySQL 的权限模型是静态的:只要 GRANT 成功,权限就一直存在,直到显式 REVOKE 或删号。没有内置定时器、钩子或自动回收机制。所谓“临时授权”,必须靠外部调度(如 cron + REVOKE)或应用层拦截。
容易踩的坑:
- 用
GRANT ... WITH GRANT OPTION授予他人授权能力,结果权限被二次扩散,失去控制 - 以为
DROP USER能“暂停”账号——实际是彻底删除,连密码历史、资源限制配置一并清空 - 在主从架构中只在主库操作,忘记从库同步延迟导致权限状态不一致
如果真要模拟临时权限,最简方案是建一个带过期时间的账号,再用事件(EVENT)自动 DROP USER,但需确保 event_scheduler=ON 且事件定义在所有节点一致。
MySQL 5.7 怎么办:没有 PASSWORD EXPIRE 怎么办
MySQL 5.7 不支持 PASSWORD EXPIRE 语法,只能靠 password_expired 字段硬设,且必须配合认证插件(如 caching_sha2_password 或 mysql_native_password)才能生效。直接 UPDATE mysql.user 表风险极高,极易锁死账号。
安全做法只有两种:
- 升级到 MySQL 8.0+(推荐,原生支持且稳定)
- 用应用层定时任务,在到期前主动执行
REVOKE ALL PRIVILEGES ON *.* FROM 'user'@'host'+FLUSH PRIVILEGES
别碰 UPDATE mysql.user SET password_expired='Y' WHERE User='xxx' —— 5.7 下多数情况会导致账号无法登录且报错 ERROR 1820 (HY000): You must reset your password using ALTER USER statement,但 ALTER USER 又不支持该版本,陷入死循环。
权限回收后用户还能连上吗?看连接池和长连接
权限变更(REVOKE 或 DROP USER)对已建立的连接完全无效。只要连接没断,用户仍能用原有权限执行语句,直到下次重连或超时断开。
这意味着:
- Web 应用用了连接池(如 HikariCP),即使你刚
REVOKE,旧连接可能继续活 30 分钟以上 -
KILL CONNECTION xxx可以强制断开,但需要知道具体线程 ID,线上批量操作容易误伤 - 更稳妥的是先
REVOKE,再等连接自然超时(由wait_timeout控制),或重启应用服务释放连接池
所以,“权限生命周期”的真实终点不是你敲下 REVOKE 的那一刻,而是最后一个持有该权限的连接真正断开的时候——这点常被忽略,尤其在高并发长连接场景里。


















