revoke super on . from 'admin'@'%'; 是唯一合法语法,因super是全局权限;mysql 8.0+已废弃super,须改用system_variables_admin等细粒度权限,并清理活跃连接及角色继承权限。

REVOKE SUPER ON *.* 是唯一合法语法
MySQL 把 SUPER 视为全局权限,它不作用于库或表,只影响整个实例行为(如 KILL、SET GLOBAL、启动复制)。因此语法强制要求作用域必须是 *.*——写成 myapp.* 或 myapp.users 会直接报错: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 已被废弃,必须换用细粒度权限
如果你的 MySQL 版本 ≥ 8.0.16(查法:SELECT VERSION();),执行 REVOKE SUPER ON *.* FROM 会报错:ERROR 3715 (HY000): The SUPER privilege is obsolete。这不是配置问题,而是 MySQL 主动移除了该权限语义。
此时必须用细粒度替代权限逐个回收,常见对应关系:
-
SYSTEM_VARIABLES_ADMIN→ 替代修改全局变量(SET GLOBAL) -
SESSION_VARIABLES_ADMIN→ 替代修改会话变量(SET SESSION) -
PERSIST_RO_VARIABLES_ADMIN→ 替代SET PERSIST(写入mysqld-auto.cnf) -
CONNECTION_ADMIN→ 替代KILL其他连接 -
SHUTDOWN→ 替代关闭实例
回收示例:REVOKE SYSTEM_VARIABLES_ADMIN, SESSION_VARIABLES_ADMIN, CONNECTION_ADMIN ON *.* FROM 'admin'@'%';
别只靠 SHOW GRANTS FOR 'admin'@'%' 看输出是否含 SUPER ——8.0+ 下它可能已不显示,但底层细粒度权限仍在生效。
撤销后旧连接仍持有权限,必须主动清理
REVOKE 只影响新建立的连接。已存在的活跃连接(包括应用长连接、DBA 客户端)仍能继续执行 KILL、SET GLOBAL max_connections 等高危操作。
不能依赖“刚执行完就安全了”,必须主动干预:
- 查活跃会话:
SELECT ID, USER, HOST, COMMAND, TIME FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'admin'; - 逐个终止:
KILL [ID];(或KILL CONNECTION [ID];) - 让应用重启连接池,或客户端手动重连
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'@'%';(更彻底,适合该角色只为该用户服务)
查角色继承关系:SELECT * FROM mysql.role_edges WHERE TO_USER = 'admin' AND TO_HOST = '%';,再对查出的角色执行 SHOW GRANTS FOR 'role_name'@'%'; 确认是否含 SUPER 或细粒度管理权限。
最易被忽略的点:权限回收不是“改完命令就结束”,而是“查清来源 + 精准撤销 + 清理残留 + 验证生效”四步闭环。任何一步跳过,都可能留下静默高危通道。











