最准最快方式是查mysql.user表super_priv='y',但mysql 8.0+必须额外联查role_edges和show grants补全角色继承权限,否则漏检。

直接查 mysql.user 表的 Super_priv 字段是最准、最快的方式,但仅适用于 MySQL 5.7 及更早版本;MySQL 8.0+ 必须额外检查角色继承路径,否则会漏掉真实拥有 SUPER 权限的用户。
查 mysql.user 表的 Super_priv 字段(MySQL 5.7 及之前)
MySQL 5.7 及更早版本中,Super_priv 是 mysql.user 表里的一个固定字段,值为 'Y' 或 'N',它直接反映该用户是否被显式授予了 SUPER 权限。这个字段不依赖角色、不经过视图转换,查它就是查最终生效状态的快照。
- 执行语句:
SELECT User, Host FROM mysql.user WHERE Super_priv = 'Y'; - 必须用有
SELECT权限访问mysql库的账号执行(如root或具备SYSTEM_USER角色的用户) - 注意大小写:
Super_priv必须大写 S 和 P,写成super_priv或SUPER_PRIV会报错或查不到 - 字段值不会自动刷新:如果刚执行过
GRANT SUPER ON *.* TO ...但没运行FLUSH PRIVILEGES,表里可能还是'N',而权限实际已生效——此时SHOW GRANTS才是真实依据
MySQL 8.0+ 必须连查 mysql.role_edges 和角色权限
MySQL 8.0 引入角色机制后,Super_priv 字段不再可靠:用户可以没有 Super_priv = 'Y',却通过角色间接获得 SUPER 权限。而角色本身不能直接被授予 SUPER(REVOKE SUPER ON *.* FROM 'role' 会报错),但角色可以被赋予包含 SUPER 的权限集(例如通过 CREATE ROLE + GRANT ... TO role 组合实现)。
- 先查哪些用户绑定了角色:
SELECT FROM_USER, FROM_HOST, TO_ROLE FROM mysql.role_edges; - 再对每个
TO_ROLE执行:SHOW GRANTS FOR 'role_name'@'%';,看输出中是否含SUPER - 注意:角色名也需带主机名(如
'myadmin'@'%'),否则SHOW GRANTS FOR会失败 - 角色权限不会体现在
mysql.user表任何字段中,只存在于内存和mysql.role_edges+mysql.role_routines等关联表
SHOW GRANTS 是唯一能验证真实权限的操作
SHOW GRANTS 不读表、不依赖字段快照,而是调用 MySQL 内部权限校验逻辑实时生成结果。它能暴露隐式权限组合(比如多个列级 SELECT 拼出完整表访问权),也能显示角色继承链(MySQL 8.0.22+ 支持 SHOW GRANTS FOR ... USING role)。
- 查当前用户:
SHOW GRANTS;—— 零权限要求,最轻量 - 查其他用户:
SHOW GRANTS FOR 'user'@'host';—— 必须严格匹配User和Host,'user'@'localhost'和'user'@'127.0.0.1'是两个不同账号 - 若提示
ERROR 1141 (42000),大概率是Host值写错,可用SELECT User, Host FROM mysql.user;先确认真实记录 - 它不显示“未显式授予但通过角色继承”的权限(旧版 MySQL 8.0),所以仍需配合
role_edges手动补全
真正难处理的是那些权限分散在 mysql.db、mysql.tables_priv 甚至列级表里的用户——他们可能没有 Super_priv = 'Y',却因组合权限获得了等效能力。这种边界情况无法靠单条 SQL 覆盖,只能靠 SHOW GRANTS + 人工交叉比对。别指望一个查询扫清所有高危账户,得把字段查、角色查、语句查三者串起来才叫完整审计。











