mysql 8.0 中角色绑定关系唯一可靠来源是 mysql.role_edges 表,from_user 存角色名,to_user/to_host 存被授者账号;需用有 select 权限账号查询,注意 host 匹配、代理用户(mysql.proxies_priv)及角色存在性校验(mysql.roles)。

查 mysql.role_edges 表直接定位角色绑定关系
MySQL 8.0 把所有角色授予行为(无论用户→角色,还是角色→角色)都存进 mysql.role_edges 表,没有单独的“角色成员视图”。FROM_USER 字段存的是角色名,TO_USER/TO_HOST 存的是被授角色的用户账号——这是唯一可靠来源。
常见错误现象:用 SHOW GRANTS FOR 'role_name'@'%' 只能看到角色自己有什么权限,完全不涉及谁绑了它;查 information_schema.APPLICABLE_ROLES 只反映当前会话已激活的角色,不是全局分配清单。
- 必须用有
SELECT权限访问mysql库的账号(如root或带SYSTEM_USER角色的用户)执行查询 - 角色名要严格匹配
FROM_USER字段值,比如'app_writer'@'%'和'app_writer'@'localhost'是两个不同角色 - 结果里
TO_USER+TO_HOST组合才是完整用户标识,'alice'和'alice'@'%'不等价
示例:查角色 app_writer 被授予了哪些用户:
SELECT TO_USER, TO_HOST FROM mysql.role_edges WHERE FROM_USER = 'app_writer' AND FROM_HOST = '%';
区分角色→用户和角色→角色两种场景
mysql.role_edges 不做类型区分,全靠字段值判断方向。如果 FROM_USER 是角色名,TO_USER 是普通用户名,那就是角色→用户授权;如果 TO_USER 也是角色名,那就是嵌套授权(角色继承)。
容易踩的坑:执行 GRANT app_writer TO 'bob'@'%' 后,TO_USER='bob';但执行 GRANT app_reader TO app_writer(省略主机名)时,MySQL 默认写入 TO_USER='app_reader'、TO_HOST='%',此时 TO_USER 字段值是另一个角色名,不是用户。
- 查“谁用了这个角色”:过滤
FROM_USER = 'role_name',看TO_USER是否为真实用户(即不在mysql.roles表中存在) - 查“这个角色继承了哪些子角色”:同样过滤
FROM_USER = 'role_name',但检查TO_USER是否存在于mysql.roles表中 - 查
mysql.roles表确认角色存在:SELECT ROLE_NAME FROM mysql.roles WHERE ROLE_NAME = 'xxx';
注意 host 匹配和权限刷新状态
mysql.role_edges 记录的是磁盘持久化状态,不受 FLUSH PRIVILEGES 影响(角色授权走的是数据字典,不是旧式权限表),但新建角色或授予权限后需确保语句已成功执行,否则表里不会有记录。
- 创建角色未显式
GRANT给任何人时,role_edges表里必然为空 - 用
CREATE ROLE 'r'@'%'建角色,再GRANT r TO 'u'@'%',才会在role_edges中生成一行 -
REVOKE r FROM 'u'@'%'后该行会被删除,不需要手动清理 - 如果
TO_HOST是'%',表示允许从任意主机连接的该用户使用此角色;如果是'192.168.1.%',则只对匹配主机生效
别漏掉代理用户(proxy user)这类特殊绑定
MySQL 支持代理用户机制(PROXY 权限),一个用户可作为另一个用户的代理登录并继承其权限。这种关系不记录在 role_edges 里,而是存在 mysql.proxies_priv 表中。
如果你发现某个用户明显拥有某角色权限但 role_edges 查不到绑定记录,就要补查代理关系:
SELECT * FROM mysql.proxies_priv WHERE Host = 'target_user_host' AND User = 'target_user_name';
代理用户本身可能没被直接授角色,但通过代理链间接获得权限,这种路径无法用 role_edges 追踪到——必须结合 CURRENT_ROLE() 和实际权限验证才能确认最终生效范围。











