mysql 8.0.19+ 可用 create user ... password expire interval n day 创建带自动过期密码的账号,仅限密码过期而非账号禁用,需配合定期清理、最小权限授权及彻底下线流程。

MySQL 8.0+ 怎么创建带自动过期时间的账号
MySQL 原生不支持“账号到期”这种操作系统级的生命周期管理,但 8.0.19+ 引入了 CREATE USER ... PASSWORD EXPIRE 和更关键的 ALTER USER ... PASSWORD EXPIRE INTERVAL N DAY,这才是外包账号临时化的可靠起点。
注意:这仅控制密码过期,不是账号禁用;过期后用户仍能连上,但执行任何操作都会报错 ERROR 1820 (HY000): You must reset your password using ALTER USER statement before executing this statement.
- 必须用 MySQL 8.0.19 或更高版本,低版本(包括 5.7)完全不识别
PASSWORD EXPIRE INTERVAL - 账号本身不会被自动删除或锁定,DBA 需配合定期清理(比如用
SELECT user, host, password_last_changed FROM mysql.user WHERE password_last_changed 找出长期未更新的账号) - 如果外包需要访问多个库,权限必须在创建后单独授权,
CREATE USER不附带任何权限
给外包账号配最小权限时,GRANT 容易漏掉哪些限制
只给 SELECT 看似安全,但实际可能暴露结构甚至数据——尤其当外包有 SHOW DATABASES 或 INFORMATION_SCHEMA 访问权时。
- 默认禁止
SHOW DATABASES:显式执行REVOKE SHOW DATABASES ON *.* FROM 'outsourcer'@'%';,否则他们能看到所有库名 -
INFORMATION_SCHEMA是只读元数据库,但TABLES、COLUMNS表可被查询,泄露表结构;如需进一步收紧,可考虑用视图封装 + 单独授权,而非直接授源表 - 避免用
GRANT ... ON *.*,哪怕只给SELECT;务必限定到具体库,例如GRANT SELECT ON `project_x`.* TO 'outsourcer'@'%'; - 如果外包要导出数据,
SELECT ... INTO OUTFILE需额外FILE权限,且该权限是全局的、无法按库限制,慎开
为什么不能靠 SET PASSWORD EXPIRE 替代创建时设有效期
SET PASSWORD EXPIRE 是立即让密码过期,而外包刚建好账号时显然不该立刻失效;它适合事后强制重置,不适合“建号即设 14 天有效期”这种场景。
-
CREATE USER 'u'@'%' IDENTIFIED BY 'p' PASSWORD EXPIRE INTERVAL 14 DAY;—— 正确:从创建时刻起倒计时 -
CREATE USER 'u'@'%'; SET PASSWORD FOR 'u'@'%' = 'p'; ALTER USER 'u'@'%' PASSWORD EXPIRE;—— 错误:密码立刻过期,外包第一次登录就卡住 -
ALTER USER 'u'@'%' PASSWORD EXPIRE INTERVAL 14 DAY;—— 可行但多一步:适用于已有账号补有效期,不如建号时一步到位
外包交接后怎么安全清理账号而不留残留
删账号不只是 DROP USER 就完事。MySQL 的权限缓存、连接池、甚至客户端预存凭证都可能导致“删了还能连”这类假象。
- 先执行
DROP USER 'outsourcer'@'%';,再立刻执行FLUSH PRIVILEGES;—— 否则权限表变更可能未生效 - 检查是否还有活跃连接:
SELECT id, user, host, db, command, time FROM information_schema.processlist WHERE user = 'outsourcer';,如有,用KILL [id]终止 - 如果应用层用了连接池(如 HikariCP、Druid),需重启应用或清空连接池,否则旧连接可能复用成功(尤其在
autoReconnect=true场景下) - 别忽略代理层:如果走 ProxySQL 或 MaxScale,账号可能在代理配置里独立维护,删 MySQL 账号后还得同步删代理配置
真正麻烦的从来不是加权限,而是确认权限彻底不可达——尤其是那些没显式 REVOKE、靠隐式继承或通配符匹配残留下来的权限路径。










