最直接方法是查询mysql.user表的Super_priv字段,值为'Y'表示拥有超级权限;MySQL 8.0+还需联查role_edges表以覆盖角色继承场景。

查 mysql.user 表的 Super_priv 字段最直接
MySQL 5.7 及以上版本中,账号是否拥有超级管理员权限(即能执行 SHUTDOWN、SET GLOBAL、KILL 等高危操作),由 mysql.user 表中的 Super_priv 列决定,值为 'Y' 表示启用。
执行以下语句即可列出所有具备该权限的账号:
SELECT Host, User FROM mysql.user WHERE Super_priv = 'Y';
注意:必须用具有 SELECT 权限的账号(如 root)连接才能查此表;普通用户默认看不到 mysql 库内容。
MySQL 8.0+ 要额外检查 role_edges 和角色继承
MySQL 8.0 引入了角色(ROLE)机制,Super_priv 可能不直接设在用户上,而是通过角色授予。仅查 mysql.user 会漏掉这类账号。
需联合查询角色分配关系:
SELECT DISTINCT u.Host, u.User<br>FROM mysql.user u<br>JOIN mysql.role_edges r ON u.User = r.to_user AND u.Host = r.to_host<br>WHERE r.from_user IN (<br> SELECT User FROM mysql.user WHERE Super_priv = 'Y'<br>);
- 上面语句找出「被授予了某个拥有
Super_priv角色」的用户 - 若角色本身是嵌套的(A 角色授给 B,B 授给用户),需递归查询,但 MySQL 原生不支持递归 CTE(8.0.14+ 才支持),此时建议先用
SHOW GRANTS FOR 'role_name'@'%';人工确认角色权限链 -
mysql.role_edges表只在 8.0+ 存在,5.7 及更早版本跳过这步
别把 root 当唯一超级账号,也别忽略空用户名
常见误判是只查 User = 'root',其实很多部署中会创建其他高权账号(如 'dba'@'%' 、'backup'@'10.0.0.%'),甚至存在匿名用户(User = '')被意外赋予 Super_priv。
务必检查全量匹配结果,重点关注:
-
User为空字符串('')的行 —— 匿名用户,权限常被忽略但实际生效 -
Host为'%'的账号 —— 允许任意主机连接,风险更高 -
Host是具体 IP 段(如'192.168.1.%')但对应业务系统已下线,属于残留高权凭证
SHOW GRANTS 能验证但不能批量筛查
SHOW GRANTS FOR 'user'@'host'; 可以确认单个账号实际拥有的权限,包括是否通过角色继承获得 SUPER,但它无法批量扫描,也不显示隐式继承路径。
典型输出中看到这一行就代表有超级权限:
GRANT SUPER ON *.* TO `admin`@`%`
但要注意:
- 如果输出里没有
SUPER,但该用户被赋予了某个角色,而角色有SUPER,SHOW GRANTS默认**不展开角色权限**(除非加USING role_name) - MySQL 8.0.16+ 支持
SHOW GRANTS FOR 'u'@'h' USING 'role_name';查角色上下文权限 - 权限可能来自
CREATE USER或GRANT ... WITH ADMIN OPTION,这些不会改变Super_priv字段值,但实际效果等同 —— 这类属于极特殊情况,一般审计不覆盖
真正要清点超级权限账号,还是得回到 mysql.user + mysql.role_edges 的组合查询,其他方式都只是辅助验证。


















