revoke super on . 是唯一合法语法;mysql将super视为全局权限,仅作用于实例级操作(如kill、set global),强制要求作用域为.,否则报错error 1221;8.0.16+已废弃super,须改用system_variables_admin等细粒度权限替代,并需主动kill活跃连接及检查角色继承。

REVOKE SUPER ON *.* 是唯一合法语法
MySQL 把 SUPER 归为全局权限,它不作用于库或表,只影响整个实例行为(如 KILL、SET GLOBAL、启动复制)。因此语法强制要求作用域必须是 *.*——写成 db_name.* 或 db_name.table_name 会直接报错:ERROR 1221 (HY000): Incorrect usage of DB GRANT and GLOBAL PRIVILEGES。
常见错误写法:
-
REVOKE SUPER ON myapp.* FROM 'admin'@'%';❌ -
REVOKE SUPER ON * FROM 'admin'@'%';❌(缺点号) -
REVOKE SUPER FROM 'admin'@'%';❌(缺ON *.*)
正确写法只有一种:REVOKE SUPER ON *.* FROM 'admin'@'%'; ✅
MySQL 8.0+ 中 SUPER 已被废弃,不能直接 REVOKE
如果你的 MySQL 版本 ≥ 8.0.16(查法:SELECT VERSION();),执行 REVOKE SUPER ON *.* FROM ... 会报错:ERROR 3715 (HY000): The SUPER privilege is obsolete。这不是配置问题,而是 MySQL 主动移除了该权限语义。
此时必须用细粒度替代权限逐个回收,常见对应关系:
-
SYSTEM_VARIABLES_ADMIN→ 替代修改全局变量(SET GLOBAL) -
SET_USER_ID→ 替代EXECUTE AS或模拟用户 -
REPLICATION_APPLIER→ 替代从库应用线程控制 -
SHUTDOWN→ 替代关闭实例 -
CONNECTION_ADMIN→ 替代KILL其他连接
查当前支持的动态权限:SHOW PRIVILEGES;;回收示例:REVOKE SYSTEM_VARIABLES_ADMIN, SET_USER_ID ON *.* FROM 'admin'@'%';
回收后旧连接仍能执行高危操作
REVOKE 只影响新建立的连接,已存在的活跃连接(包括应用长连接、DBA 客户端)仍持有原 SUPER 或等效权限,可继续 KILL、SET GLOBAL max_connections 等操作。
必须主动干预:
- 查活跃会话:
SELECT ID, USER, HOST, COMMAND, TIME FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'admin'; - 逐个
KILL [ID];或批量终止:KILL QUERY/KILL CONNECTION - 让应用重启连接池,或客户端手动重连
别依赖 FLUSH PRIVILEGES;——它对动态权限变更无效,且在 8.0+ 中也不必要。
别漏掉角色间接授予的 SUPER 权限
如果用户是通过角色获得高危能力(例如:GRANT SUPER ON *.* TO 'dba_role'; GRANT 'dba_role' TO 'admin'@'%';),那么只对用户执行 REVOKE 不生效。
两种处理方式:
- 从角色本身撤权:
REVOKE SUPER ON *.* FROM 'dba_role';(适用于角色还需保留给其他人) - 解绑角色:
REVOKE 'dba_role' FROM 'admin'@'%';(更常用,直接切断继承链)
验证是否清干净:SHOW GRANTS FOR 'admin'@'%'; 输出里不应再出现 SUPER 或任何替代动态权限;同时检查 mysql.role_edges 表确认无残留关联。
真正麻烦的不是语法写错,而是权限叠加和连接缓存——一个 SHOW GRANTS 看不出全貌,一次 KILL 漏掉一个连接,就可能让降权失效。











