撤销SUPER权限必须用REVOKE SUPER ON .,因其是全局权限;MySQL 8.0+已废弃SUPER,需改用SYSTEM_VARIABLES_ADMIN、CONNECTION_ADMIN等细粒度权限,并清理活跃连接及角色间接授权。

MySQL中撤销SUPER权限不能只靠REVOKE ALL PRIVILEGES,必须显式用REVOKE SUPER ON *.*,且8.0+版本已废弃该权限,需换用细粒度替代权限。
为什么REVOKE SUPER ON myapp.*会报错
SUPER是全局权限(global privilege),它不作用于库或表,只影响整个实例行为(如KILL、SET GLOBAL、启动复制)。MySQL强制要求其作用域只能是*.*——写成myapp.*或myapp.users会直接报错:ERROR 1221 (HY000): Incorrect usage of DB GRANT and GLOBAL PRIVILEGES。
- 正确写法唯一:
REVOKE SUPER ON *.* FROM 'admin'@'%'; - 错误写法示例:
REVOKE SUPER ON myapp.* FROM 'admin'@'%';❌ - 错误写法示例:
REVOKE SUPER FROM 'admin'@'%';❌(缺ON *.*)
MySQL 8.0+ 中SUPER已被废弃,必须用细粒度权限替代
执行REVOKE SUPER ON *.* FROM ...在8.0.16+会报错:ERROR 3715 (HY000): The SUPER privilege is obsolete。这不是配置问题,而是MySQL主动移除了该权限语义。
- 对应关系必须手动映射:
SYSTEM_VARIABLES_ADMIN→ 替代SET GLOBAL,CONNECTION_ADMIN→ 替代KILL其他连接,SHUTDOWN→ 替代关实例 - 推荐回收组合:
REVOKE SYSTEM_VARIABLES_ADMIN, CONNECTION_ADMIN, SHUTDOWN ON *.* FROM 'admin'@'%'; -
SHOW GRANTS FOR 'admin'@'%'可能不显示SUPER,但底层细粒度权限仍在生效,务必查实输出中是否含SYSTEM_VARIABLES_ADMIN等
撤销后旧连接仍持有权限,必须主动清理
REVOKE只影响新建立的连接。已存在的活跃连接(包括应用长连接、DBA客户端)仍能继续执行KILL、SET GLOBAL等高危操作。
- 先查活跃会话:
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毫无意义。
- 查角色绑定:
SELECT FROM_HOST, FROM_USER FROM mysql.role_edges WHERE TO_USER = 'admin' AND TO_HOST = '%'; - 解绑角色:
REVOKE 'dba_role' FROM 'admin'@'%'; - 若角色本身还持有细粒度权限,需同步清理角色的权限定义
最危险的盲区在于:你以为执行完所有REVOKE就安全了,但应用连接池里的长连接还在用旧权限跑SET GLOBAL max_connections——这种残留权限不会出现在SHOW GRANTS里,也绕过了所有语法校验。


















