撤销super权限必须使用revoke super on . from 'user'@'host';,因其属全局权限,不作用于库或表;all privileges不包含super,需显式撤销;已存在连接不受影响,须主动kill或重启连接池;若通过角色授予,需从角色撤销或剥离角色。

SUPER 权限只能在 *.* 上撤销,写成 db_name.* 或 db_name.table_name 会直接报错。
必须用 *.* 作用域撤销 SUPER
MySQL 把 SUPER 归为全局权限(global privilege),它不作用于某个库或某张表,而是影响整个实例的行为,比如杀连接、修改全局变量、启动从库等。因此语法上强制要求作用域为 *.* ——哪怕你当初是用 GRANT SUPER ON myapp.* TO 'admin'@'%' 这种错误写法授的(其实会静默降级为 *.*),撤的时候也必须回归正确形式。
-
REVOKE SUPER ON *.* FROM 'admin'@'%';✅ 正确 -
REVOKE SUPER ON myapp.* FROM 'admin'@'%';❌ 报错:ERROR 1221 (HY000): Incorrect usage of DB GRANT and GLOBAL PRIVILEGES -
REVOKE SUPER ON myapp.users FROM 'admin'@'%';❌ 同样报错,且不会部分生效
ALL PRIVILEGES 不包含 SUPER,也不能靠它一并撤掉
很多人误以为 REVOKE ALL PRIVILEGES ON *.* FROM 'u'@'h'; 能顺带清掉 SUPER,但这是错的。ALL PRIVILEGES 是一组常规 DML/DDL 权限的集合(SELECT、INSERT、CREATE、DROP 等),SUPER 和 GRANT OPTION、REPLICATION CLIENT 等都属于独立的“管理类权限”,不在其中。
- 执行
REVOKE ALL PRIVILEGES ON *.* FROM 'admin'@'%';后,SUPER依然存在 - 要彻底清理,得显式加上:
REVOKE ALL PRIVILEGES, SUPER, GRANT OPTION ON *.* FROM 'admin'@'%'; - 验证方式:运行
SHOW GRANTS FOR 'admin'@'%';,确认输出里不再出现SUPER
撤销后不重连,旧连接仍能执行 KILL 或 SET GLOBAL
REVOKE 只影响新建立的连接。如果用户当前有活跃连接(比如应用长连接、DBA 正在用的客户端),那些连接持有的权限不会被实时剥夺——SUPER 就是典型,它允许用户继续 KILL 其他线程、改 max_connections 等。
- 不能依赖“刚执行完 REVOKE 就安全了”
- 生产环境建议配合
SELECT ID, USER, HOST, COMMAND, TIME FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'admin';查活跃会话 - 必要时主动断开:
KILL [connection_id];,或让应用重启连接池 -
FLUSH PRIVILEGES;对SUPER撤销不是必需的(MySQL 8.0+ 自动刷新),但它不解决已存在连接的问题
别漏掉角色间接授予的 SUPER
如果用户是通过角色获得 SUPER(例如 GRANT SUPER ON *.* TO 'myrole'; GRANT 'myrole' TO 'admin'@'%';),那么只对用户执行 REVOKE SUPER ON *.* FROM 'admin'@'%'; 是无效的——权限来自角色,不是直授。
- 先查角色归属:
SELECT * FROM mysql.role_edges WHERE TO_HOST = '%' AND TO_USER = 'admin'; - 再从角色撤权:
REVOKE SUPER ON *.* FROM 'myrole'; - 或者直接剥离角色:
REVOKE 'myrole' FROM 'admin'@'%'; - 注意:角色本身也要验证是否还持有
SUPER,否则重新赋给别的用户又会复现
真正难的不是写对那条 REVOKE,而是确认 SUPER 到底从哪来、还在不在哪个连接里跑着、有没有被角色绕过——这些地方一漏,高危权限就还在暗处呼吸。











