MySQL不支持原生临时账号有效期,唯一可行方案是CREATE USER PASSWORD EXPIRE AFTER N(8.0.11+),它强制N天后首次操作报错ERROR 1820要求重置密码,需配合SET PERSIST default_password_lifetime = 0防全局覆盖,且不适用于5.7等低版本。

MySQL 没有“临时账号有效期”这个功能,所谓“带期限的访问权”,本质是靠密码过期机制 + 应用层拦截来凑出来的——直接建个账号设个时间,就指望它到点自动失效,会出事。
CREATE USER PASSWORD EXPIRE AFTER N 是唯一能落地的“有效期”语法
MySQL 8.0.11+ 支持在创建用户时用 PASSWORD EXPIRE AFTER N(N 为整数天)设定相对有效期。它不是“账号到期删除”,而是让密码在 N 天后强制重置,用户登录后首次执行任意语句就会被拦住,报错 ERROR 1820 (HY000): You must reset your password using ALTER USER statement before executing this statement。
-
CREATE USER 'tool_user'@'10.20.%' IDENTIFIED BY 't00l_2026' PASSWORD EXPIRE AFTER 3;—— 创建即生效,3 天后首次操作失败 - 必须搭配
SET PERSIST default_password_lifetime = 0;,否则全局设置(如 90 天)可能覆盖用户级策略 - 低版本 MySQL(如 5.7)完全不识别该语法,执行会静默失败或报错
ERROR 1064 - 如果第三方工具不支持自动重置密码(绝大多数都不支持),那它连一次有效查询都完不成——别指望它能自己处理
ERROR 1820
GRANT 权限前必须先 CREATE USER,且不能只给 USAGE
临时账号不是“加权限”,而是新建一个独立用户实体。直接 GRANT SELECT ON `app`.* TO 'tool_user'@'10.20.%'; 会失败,因为用户还不存在;而 GRANT USAGE ON *.* 看似无害,实则等于只开了连接通道,后续所有操作都会被拒绝(ERROR 1044)。
- 先执行
CREATE USER 'tool_user'@'10.20.%' IDENTIFIED BY 't00l_2026' PASSWORD EXPIRE AFTER 3; - 再执行
GRANT SELECT, SHOW VIEW ON `app`.* TO 'tool_user'@'10.20.%';—— 明确限定库名,禁用通配符* - 显式执行
FLUSH PRIVILEGES;,避免跨版本或配置差异导致权限未加载 - 务必
REVOKE SHOW DATABASES ON *.* FROM 'tool_user'@'10.20.%';,否则工具能列出所有库名,暴露架构
EVENT 自动锁定只能补位,不能替代应用层判断
用 ALTER USER ... ACCOUNT LOCK 配合事件调度器,确实能在指定时间点把账号锁住,但它只影响新连接。已建立的长连接(比如第三方工具维持的连接池)不会中断,权限照常生效——你看到“已过期”日志,但数据还在被读取。
- 启用调度器:
SET GLOBAL event_scheduler = ON;(需SUPER权限) - 创建锁定事件:
CREATE EVENT lock_tool_user ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 3 DAY DO ALTER USER 'tool_user'@'10.20.%' ACCOUNT LOCK; - 事件依赖系统时间准确、MySQL 未重启丢失、event_scheduler 未被意外关闭——任一环节断掉,就失效
- 真正可控的方式,是在你的 API 网关或数据库代理层做连接前校验:查
mysql.user表中password_last_changed和password_life_time,算出是否已超期,超期则拒绝建连
第三方工具连不上?先查 account_locked 和 password_expired 状态
连不上不一定是密码错,大概率是账号被锁或密码过期了。MySQL 不会主动告诉你原因,得手动查状态:
- 检查账号是否被锁:
SELECT user, host, account_locked FROM mysql.user WHERE user = 'tool_user'; - 查密码过期状态:
SELECT user, host, password_expired, password_last_changed, password_lifetime FROM mysql.user WHERE user = 'tool_user'; - 如果
account_locked = 'Y',用ALTER USER 'tool_user'@'10.20.%' ACCOUNT UNLOCK;解锁 - 如果
password_expired = 'Y',说明已触发过期逻辑,此时SET PASSWORD无效,必须由管理员执行ALTER USER 'tool_user'@'10.20.%' IDENTIFIED BY 'newpass';
最易被忽略的一点:第三方工具通常复用连接、缓存认证结果,哪怕你立刻锁了账号或改了密码,它可能还在用旧连接继续查数据——权限回收不是秒级的,得配合连接池刷新或服务重启才能彻底切断。











