最准确的方法是执行select user, host from mysql.user where super_priv = 'y';,但mysql 8.0+需结合role_edges表检查角色继承,因super权限可能通过角色间接赋予且show grants无法反映真实状态。

查 mysql.user 表里 Super_priv 为 'Y' 的用户
MySQL 的超级权限(SUPER)直接控制服务级操作,比如杀连接、修改全局变量、主从切换等,不通过常规权限表(如 mysql.tables_priv)管理,只存在 mysql.user 表的字段里。直接查这个表最准、最快。
-
SELECT User, Host FROM mysql.user WHERE Super_priv = 'Y';是唯一可靠的一线检查方式 - 注意区分大小写:MySQL 8.0+ 默认严格校验
Host值(比如'localhost'和'127.0.0.1'是两个用户) - 执行前必须有
SELECT权限访问mysql系统库,普通账号通常没这权限 —— 这就是为什么运维常要登录 root 或具备SYSTEM_USER角色的账号才能查
MySQL 8.0+ 要额外看 role_edges 和角色继承链
8.0 引入了角色(ROLE),SUPER 权限可能不是直接授给用户,而是通过角色间接赋予。只查 mysql.user 会漏掉这类情况。
- 先查用户被授予了哪些角色:
SELECT TO_USER, TO_HOST, FROM_USER, FROM_HOST FROM mysql.role_edges WHERE TO_USER = 'xxx'; - 再查这些角色本身有没有
SUPER:SELECT User, Host FROM mysql.user WHERE User IN ('role1', 'role2') AND Super_priv = 'Y'; - 角色不能嵌套授权
SUPER—— MySQL 明确禁止把SUPER授给角色,但旧版本升级后残留配置或手动改表可能导致异常,需人工核对
SHOW GRANTS 无法反映真实 SUPER 状态
SHOW GRANTS FOR 'u'@'h' 看起来直观,但它只展示显式授予的权限语句,不体现系统表字段值,也不解析角色继承。对 SUPER 来说,它经常“不显示但实际有效”。
- 常见错觉:执行
SHOW GRANTS没看到GRANT SUPER ON *.*,就以为没权限 —— 实际可能是通过角色继承,或早期用INSERT INTO mysql.user手动改过字段 -
SHOW GRANTS输出里永远不出现SUPER字样,哪怕用户真有该权限(这是 MySQL 的设计限制) - 验证是否真能用:可以试执行
KILL 123或SET GLOBAL max_connections = 1000;,比看语句更直接
权限回收时 DROP ROLE 不等于清除 SUPER
删掉一个带 SUPER 的角色,并不会自动清理已通过该角色获得权限的用户字段 —— 因为权限在用户行里是静态快照,不是实时计算的。
- 删角色后,原用户仍可能保留
Super_priv = 'Y',除非你显式执行REVOKE SUPER ON *.* FROM 'u'@'h'; -
REVOKE对角色无效:REVOKE SUPER ON *.* FROM 'myrole';会报错,因为角色不能持有SUPER - 最稳妥的清理路径:先
REVOKE用户的SUPER,再DROP ROLE,最后FLUSH PRIVILEGES;(虽然 8.0+ 多数情况不需要,但涉及手动改表时建议加上)
事情说清了就结束。真正难的不是查到谁有 SUPER,而是确认它从哪来、能不能被回收、会不会因角色变更而意外残留 —— 尤其在混合使用直接授权和角色的环境里。











