查 mysql 超级用户需分两步:mysql 5.7 及更早版本直接查 mysql.user 表 super_priv='y';mysql 8.0+ 还必须通过 mysql.role_edges 和 show grants 检查角色继承,并确认 set role 已执行,否则可能漏判。

查 mysql.user 表的 Super_priv 字段是最直接的起点,但仅靠它在 MySQL 8.0+ 中一定会漏人——因为角色继承的 SUPER 权限不写入该字段。
查 mysql.user 表:只对 MySQL 5.7 及更早版本“全准”
执行 SELECT User, Host FROM mysql.user WHERE Super_priv = 'Y'; 就能拿到所有显式授予 SUPER 的账号。但注意:
-
Super_priv必须严格大写 S 和 P;写成super_priv或SUPER_PRIV会查不到或报错 - 必须用有
SELECT ON mysql.*权限的账号(如root或带SYSTEM_USER角色的用户)执行 - 刚执行过
GRANT SUPER ON *.* TO 'u'@'h'但没运行FLUSH PRIVILEGES,表里可能还是'N',而权限已实际生效 -
mysql.session、mysql.infoschema等系统账号也显示'Y',但它们不能登录,不算可被滥用的“真实”超级账号
MySQL 8.0+ 必须补查 mysql.role_edges 和角色权限链
角色本身不能被直接授予 SUPER(GRANT SUPER ON *.* TO 'role'@'%' 会报错),但用户可通过激活角色间接获得该权限。只查 mysql.user 会漏掉这类账号。
- 先查谁绑定了角色:
SELECT FROM_USER, FROM_HOST, TO_ROLE FROM mysql.role_edges; - 对每个
TO_ROLE,执行SHOW GRANTS FOR 'role_name'@'%'(注意:角色名必须带主机名,否则失败) - 若输出含
GRANT SUPER ON *.* TO,说明该角色链能提供 SUPER;再反查哪些用户被授了这个角色:SELECT User, Host FROM mysql.user u JOIN mysql.role_edges r ON u.User = r.FROM_USER AND u.Host = r.FROM_HOST WHERE r.TO_ROLE = 'xxx'; - 用户必须已执行过
SET ROLE 'xxx';才能激活权限;否则即使查到角色链,实际也没 SUPER
SHOW GRANTS 永远不显示 SUPER,别拿它当依据
SHOW GRANTS FOR 'u'@'h' 输出里永远不会出现 SUPER 关键字,哪怕用户真有该权限。这是 MySQL 内部设计限制,不是你查错了。
- 它只展示显式
GRANT语句,不解析角色继承,也不读取mysql.user字段快照 - 没看到
GRANT SUPER ON *.* TO,不代表没权限——可能是角色继承,也可能是早期用INSERT INTO mysql.user直接改过字段 - 验证是否真能用:登录该账号后执行
KILL QUERY 1或SET GLOBAL max_connections = 1000,比看语句更直接
真正难的不是查出结果,而是判断“这个账号现在到底有没有 SUPER”——它取决于字段值、角色绑定状态、角色是否被激活、以及权限是否已刷新。四个条件缺一不可,漏掉任何一个都可能误判。尤其是 SET ROLE 是否执行过,这一步没法从元数据里自动推断,只能人工确认或实测。











