必须联合查询mysql.role_edges、information_schema.applicable_roles及各角色的show grants结果,才能准确还原用户最终有效权限;因角色授权、激活状态与权限继承三者不同步,无法一键汇总。

不能只靠 SHOW GRANTS 看清用户继承的角色权限——它压根不展开角色链,也不反映激活状态。必须查 mysql.role_edges + INFORMATION_SCHEMA.APPLICABLE_ROLES + 各角色自身的权限语句,三者缺一不可。
查用户被授予了哪些角色(静态授权关系)
角色是否“被授给用户”,只记录在 mysql.role_edges 表里,字段含义固定:FROM_USER 是角色名,TO_USER 是接收者(用户或另一角色)。
- 查用户
'app_user'直接获得的角色:SELECT FROM_USER, FROM_HOST FROM mysql.role_edges WHERE TO_USER = 'app_user' AND TO_HOST = '%'; - 注意
TO_HOST必须匹配实际授权时的 host(比如'%'、'10.0.0.%'),否则查不到 - 该表不区分“已激活”和“未激活”,只表示“曾经被 GRANT 过”
查当前会话实际激活的角色(运行时状态)
即使角色被授予,没 SET ROLE 或没设为默认角色,权限就等于不存在。登录后必须看 INFORMATION_SCHEMA.APPLICABLE_ROLES 才知道哪些角色真正在用。
- 查当前会话已激活的角色:
SELECT ROLE_NAME, IS_ASSIGNED FROM INFORMATION_SCHEMA.APPLICABLE_ROLES WHERE IS_ASSIGNED = 'YES'; -
CURRENT_ROLE()只返回当前生效的那个角色(单值),不是全部;IS_ASSIGNED = 'YES'才代表已激活 - 如果结果为空,说明所有角色都未激活——此时用户只有
mysql.user表里直授的权限
查某个角色自身拥有的权限(不能靠 SHOW GRANTS FOR ... USING)
SHOW GRANTS FOR 'u'@'h' USING 'role_name' 只显示该角色“自己被显式授予”的权限,不会递归展开它依赖的上游角色(比如 role_a → role_b → role_c)。要完整还原权限,得一层层查。
- 对每个已激活角色,单独执行:
SHOW GRANTS FOR 'role_name'@'%'; - 若该角色本身又被其他角色授予(即它是
TO_USER),就得再查它的上游:SELECT FROM_USER FROM mysql.role_edges WHERE TO_USER = 'role_name' AND TO_HOST = '%'; - MySQL 8.0.14+ 支持 CTE 递归查链,但
role_edges不保证无环,手动拼接更稳妥
为什么不能一键汇总?关键难点在哪
真正难的不是查表,而是对齐三件事:谁被授予了哪些角色(role_edges)、哪些角色当前激活(APPLICABLE_ROLES)、每个角色自己有什么权限(SHOW GRANTS FOR role)。这三者时间点不同步——角色可能刚被 GRANT 但还没 SET ROLE,也可能被 DROP ROLE 但用户行里的权限字段没清理干净。没人能绕过这个事实直接输出“最终有效权限”。











