最准确方法是执行SELECT User, Host FROM mysql.user WHERE Super_priv = 'Y';,MySQL 8.0+还需联合mysql.role_edges检查角色继承路径,因SUPER权限可能通过角色间接赋予且SHOW GRANTS无法反映。

直接查 mysql.user 表的 Super_priv 字段最准
MySQL 的 SUPER 权限不走常规权限表(比如 mysql.db 或 mysql.tables_priv),只存在 mysql.user 表的 Super_priv 列里,值为 'Y' 或 'N'。其他方式——包括 SHOW GRANTS、information_schema 视图、甚至 SELECT * FROM mysql.user 不带条件——都会漏判或误判。
必须用这个语句:
SELECT User, Host FROM mysql.user WHERE Super_priv = 'Y';
注意点:
-
Super_priv是大小写敏感的字段名,不能写成super_priv或SUPER_PRIV - 执行者需要有
SELECT权限访问mysql.user表,普通用户默认没有,得用root或被显式授权过的账号 - 结果里的
Host值必须和实际登录时的 host 完全一致('localhost'≠'127.0.0.1')
MySQL 8.0+ 必须额外检查角色继承路径
8.0 引入角色后,SUPER 权限可能没直接赋给用户,而是通过角色间接赋予。此时 Super_priv = 'Y' 在 mysql.user 里是 'N',但用户仍实际拥有该权限。
查角色链要两步:
先找哪些角色有 SUPER(角色本身不能直接被授 SUPER,但可通过 SET DEFAULT ROLE 激活含该权限的角色):
SELECT DISTINCT r.ROLE_NAME FROM mysql.role_edges r JOIN mysql.user u ON r.TO_HOST = u.Host AND r.TO_USER = u.User WHERE u.Super_priv = 'Y' OR r.FROM_HOST = '%' OR r.FROM_USER IN (SELECT Role_name FROM mysql.role_edges WHERE TO_USER = u.User);
更实用的做法是联合查 mysql.role_edges 和 mysql.user:
SELECT u.User, u.Host FROM mysql.user u WHERE u.Super_priv = 'Y' UNION SELECT u.User, u.Host FROM mysql.user u INNER JOIN mysql.role_edges re ON u.User = re.TO_USER AND u.Host = re.TO_HOST INNER JOIN mysql.user r ON re.FROM_USER = r.User AND r.Super_priv = 'Y';
关键提醒:
-
REVOKE SUPER ON *.* FROM 'rolename'会报错:角色不能直接持有SUPER,只能由用户激活后临时生效 - 用户必须已执行
SET ROLE 'xxx';才能激活角色权限;否则即使查到角色链,实际也无SUPER -
SHOW GRANTS FOR 'u'@'h'永远不会显示角色继承来的SUPER,别依赖它做判断
SHOW GRANTS 查不到 SUPER?不是 bug,是设计如此
SHOW GRANTS 只输出显式授予的权限语句,不反映 mysql.user 表里的权限位,也不解析角色继承。所以即使某用户 Super_priv = 'Y',SHOW GRANTS 输出里也不会出现 SUPER 字样——除非你手动执行过 GRANT SUPER ON *.* TO ...。
常见误解场景:
- 执行
SHOW GRANTS FOR 'admin'@'%';没看到SUPER,就以为没权限 → 实际可能mysql.user里是'Y' - 在 8.0+ 环境下给用户设了默认角色,但忘了
SET ROLE→SHOW GRANTS和实际权限都不包含SUPER - 用低权限账号执行
SHOW GRANTS FOR→ 直接报错ERROR 1142,误以为语法错,其实是缺SELECT ON mysql.user
结论:查 SUPER 别碰 SHOW GRANTS,它在这事上就是个摆设。
为什么不能只靠 FLUSH PRIVILEGES 后再查?
FLUSH PRIVILEGES 只强制重载磁盘上的权限数据到内存,但它不影响查询结果的“准确性”——因为 SELECT ... FROM mysql.user 读的就是磁盘表,不是缓存。真正容易被忽略的是权限生效时机:
- 修改
mysql.user表后,已有连接不会立即丢失SUPER权限,新连接才按新状态判定 - 如果用户正在用
SUPER杀连接或改全局变量,改完表不FLUSH,旧连接仍能继续操作 -
FLUSH PRIVILEGES对角色权限无效:角色映射关系存在内存中,重启或显式SET ROLE才刷新
所以查权限时,FLUSH PRIVILEGES 不是必要步骤;但如果你刚手工 UPDATE 过 mysql.user,且想立刻让新连接生效,它就有用。


















