mysql中temporary权限只能在.上撤销,需同时处理grant option、super_priv、角色绑定及连接缓存;真正生效须重连或kill连接。

REVOKE TEMPORARY 权限必须在 *.* 上执行
MySQL 中 TEMPORARY 权限是全局权限,只能作用于 *.*(所有数据库),不能指定到某个库或表。写成 REVOKE TEMPORARY ON mydb.* FROM 'u'@'%' 会报语法错误:ERROR 1044 (42000): Access denied for user ... to database 'mydb'。
正确做法是:
REVOKE TEMPORARY ON *.* FROM 'u'@'%';- 必须显式加上
GRANT OPTION(如果用户有):REVOKE GRANT OPTION ON *.* FROM 'u'@'%';,否则该用户仍可把TEMPORARY权限授给他人 - 执行后立即生效,但已存在的连接不会刷新权限视图——用户仍可在当前会话中继续
CREATE TEMPORARY TABLE
别漏掉 mysql.user 表里的 Super_priv 字段
TEMPORARY 权限本身不依赖 Super_priv,但拥有 SUPER 权限的用户可以绕过几乎所有限制,包括无视 TEMPORARY 是否被撤回——只要他还能连上,就能创建临时表。
所以真正要封死,得查并清空管理字段:
- 先确认:
SELECT Host, User, Super_priv FROM mysql.user WHERE User = 'u' AND Host = '%'; - 若为
'Y',执行:UPDATE mysql.user SET Super_priv = 'N' WHERE User = 'u' AND Host = '%'; - 紧接着必须运行:
FLUSH PRIVILEGES;(因为直接改了系统表)
回收后仍能建临时表?检查是否绑定了角色
如果用户通过角色获得 TEMPORARY 权限,只对用户本体执行 REVOKE 是无效的。角色权限不会出现在 SHOW GRANTS FOR 'u'@'%' 的输出里,但真实生效。
排查步骤:
- 查绑定关系:
SELECT FROM_HOST, FROM_USER FROM mysql.role_edges WHERE TO_USER = 'u' AND TO_HOST = '%'; - 对每个角色执行:
REVOKE 'role_name' FROM 'u'@'%'; - 再确认角色权限是否残留:
SHOW GRANTS FOR 'role_name'@'%';
USAGE 权限无法撤销,且旧连接缓存权限最危险
USAGE 是空权限,所有用户默认拥有,它允许登录但不做任何事——但它不会被 REVOKE 影响,也无法从 mysql.user 表中删掉。这意味着:哪怕你做完所有操作,SHOW GRANTS 看起来干干净净,用户只要没断开连接,就仍能用旧权限建临时表。
真正落地的回收动作只有两个:
- 通知应用层主动重连(或滚动重启)
- 或在数据库侧 kill 对应连接:
KILL CONNECTION [id];(需CONNECTION_ADMIN或SUPER权限)
临时表权限的“回收完成”不是靠命令执行完就结束,而是以连接状态为准——这点最容易被忽略。











