mysql 8.0+ 中 revoke super on . 报错 error 1221,因 super 是全局权限,正确语法为 revoke super from 'user'@'host';,且需 flush privileges 生效,并主动 kill 活跃连接。

直接执行 REVOKE SUPER ON *.* FROM 会报错
MySQL 8.0+ 中,SUPER 权限已被拆分为更细粒度的权限(如 SET_USER_ID、SYSTEM_VARIABLES_ADMIN 等),但兼容模式下仍保留该名称。不过你不能用 REVOKE SUPER ON *.* FROM 'user'@'host' 直接回收——MySQL 会报错 ERROR 1221 (HY000): Incorrect usage of DB GRANT and GLOBAL PRIVILEGES,因为 SUPER 是全局权限,语法必须省略 ON *.*。
- 正确写法是:
REVOKE SUPER FROM 'user'@'host'; - 必须先确保该用户没有被授予
SYSTEM_USER(MySQL 8.0.12+ 引入的更高阶权限,会隐式包含SUPER的能力) - 执行后需运行
FLUSH PRIVILEGES;才能立即生效(虽然多数情况下自动刷新,但生产环境建议显式调用)
回收前先查清用户实际持有的高危权限
仅撤掉 SUPER 不代表用户失去所有提权能力。有些权限组合也能绕过限制,比如同时拥有 UPDATE + SELECT 权限在 mysql.user 表上,就可能改写自己的认证信息。
- 检查用户全部权限:
SHOW GRANTS FOR 'user'@'host'; - 重点留意:
SYSTEM_VARIABLES_ADMIN、SERVER_ADMIN、PERSIST_RO_VARIABLES_ADMIN、ROLE_ADMIN—— 这些在 MySQL 8.0+ 中可替代SUPER完成多数系统级操作 - 若用户有
GRANT OPTION,还要确认它没把高权限转授给他人
MySQL 5.7 和 8.0+ 的行为差异很关键
MySQL 5.7 允许 REVOKE SUPER ON *.*(虽不推荐),而 8.0+ 严格禁止这种写法;同时 8.0+ 默认启用 sql_mode=STRICT_TRANS_TABLES,如果回收权限时用户正在执行长事务或持有元数据锁,REVOKE 可能被阻塞。
- 5.7 下可用:
REVOKE SUPER ON *.* FROM 'user'@'host';(兼容写法,但官方已标记为过时) - 8.0+ 必须用:
REVOKE SUPER FROM 'user'@'host'; - 回收后验证是否生效:
SELECT * FROM performance_schema.role_edges WHERE TO_HOST = 'host' AND TO_USER = 'user';(检查是否还通过角色间接获得权限)
权限回收后服务连不上?注意 max_connections 和 read_only 的副作用
SUPER 权限常被用来临时绕过 read_only=ON 或动态修改 max_connections。一旦回收,用户再执行 SET GLOBAL read_only = OFF; 或 SET GLOBAL max_connections = 1000; 就会报错 ERROR 1227 (42501): Access denied; you need (at least one of) the SYSTEM_VARIABLES_ADMIN privilege(s) for this operation。
- 如果应用依赖这类动态设置,得提前把对应权限(如
SYSTEM_VARIABLES_ADMIN)单独授予该用户,而不是留着SUPER - 检查
read_only当前值:SELECT @@global.read_only; - 确认连接池是否因权限变更触发重连失败——部分 JDBC 驱动在初始化时尝试
SET NAMES或SELECT @@version,一般不受影响,但自定义初始化 SQL 若含SET GLOBAL就会中断
回收 SUPER 不是单点操作,本质是权限体系重构。最容易被忽略的是:权限变更不会自动终止已存在的连接,那些连接仍以旧权限运行,直到断开重连。线上操作前,最好先 KILL 对应用户的活跃会话,或协调业务侧滚动重启连接池。











