要查看当前会话已激活的角色列表,应使用SELECT CURRENT_ROLE();,它直接返回逗号分隔的已激活角色名(如'role_admin@%,role_report@%'),返回NONE表示未激活任何角色。

查看当前会话已激活的角色列表
MySQL 8.0+ 支持基于角色的权限管理,但角色需被显式 SET ROLE 激活后才生效。要确认当前会话实际在用哪些角色,不能只查 mysql.role_edges 或用户授权表,而要看会话级状态。最直接的方式是查询 INFORMATION_SCHEMA.APPLICABLE_ROLES 视图,并筛选出已激活的:
SELECT * FROM INFORMATION_SCHEMA.APPLICABLE_ROLES WHERE IS_GRANTABLE = 'YES' AND IS_DEFAULT_ROLE = 'YES';
不过这个视图只反映“默认角色”和“可授予状态”,不等于当前激活状态。真正反映当前会话角色的是 CURRENT_ROLE() 函数:
SELECT CURRENT_ROLE();
它返回一个逗号分隔的字符串,例如 'role_admin@%,role_report@%',表示当前会话已激活的全部角色。注意:若返回 NONE,说明没有角色被激活(即使用户被授予了角色,也需手动 SET ROLE 或登录时由 SET DEFAULT ROLE 触发)。
确认指定用户在新连接中默认激活哪些角色
用户登录后自动激活的角色,取决于其 DEFAULT ROLE 设置。要查某用户(如 'app_user'@'localhost')的默认角色配置,需查 mysql.default_roles 系统表(MySQL 8.0.16+):
SELECT HOST, USER, ROLE_HOST, ROLE_USER FROM mysql.default_roles WHERE USER = 'app_user' AND HOST = 'localhost';
如果该表为空,说明未显式设置默认角色——此时即使用户被授予了多个角色,新连接也不会自动激活任何角色,CURRENT_ROLE() 将始终为 NONE。补救方式是执行:
ALTER USER 'app_user'@'localhost' DEFAULT ROLE 'role_api', 'role_read';
注意:DEFAULT ROLE 只影响后续新连接,不影响已有会话;且必须确保所列角色确实已被授予该用户(通过 GRANT role_name TO 'user'@'host'),否则会报错 ERROR 3530 (HY000): Cannot grant role 'xxx' to user 'yyy'@'zzz': role does not exist or is not granted to the user。
检查用户是否真的被授予了某个角色
角色是否“存在”和是否“被授予给用户”是两回事。常见误区是看到 mysql.role_edges 里有记录,就以为用户能用该角色——其实还要确认该角色是否被 GRANT 给用户,且未被 REVOKE。查授予关系最稳妥的方式是:
SELECT FROM_HOST, FROM_USER, TO_HOST, TO_USER, WITH_ADMIN_OPTION FROM mysql.role_edges WHERE TO_USER = 'app_user' AND TO_HOST = 'localhost';
如果结果为空,说明该用户未被授予任何角色;若有结果,再结合 mysql.proxies_priv(极少用)和实际权限验证。另外,角色本身是否有效,可通过查询 mysql.roles_mapping(MySQL 8.0.19+)或尝试 SHOW GRANTS FOR ROLE 'role_name'@'%' 来确认。
为什么 SHOW GRANTS FOR 'user'@'host' 不显示角色权限?
SHOW GRANTS 默认只显示直接授予用户的权限(如 GRANT SELECT ON db.* TO ...),**不会展开角色所带的权限**。即使用户被授予了 role_admin,且该角色拥有 ALL PRIVILEGES ON *.*,SHOW GRANTS FOR 'u'@'h' 也只会输出 GRANT role_admin@'%' TO 'u'@'h',不会列出角色内部权限。这是设计使然,避免权限爆炸式展示。如需完整权限视角,必须手动组合:
- 查用户直授权限:
SHOW GRANTS FOR 'u'@'h' - 查用户被授哪些角色:
SELECT * FROM mysql.role_edges WHERE TO_USER='u' AND TO_HOST='h' - 对每个角色,再查其权限:
SHOW GRANTS FOR ROLE 'role_name'@'host_pattern'
没有单条 SQL 能自动拼出“用户最终所有权限”的完整清单——MySQL 不提供类似 PostgreSQL 的 pg_auth_members + pg_role 联合视图。这也是最容易被忽略的复杂点:权限调试时,不能只盯 SHOW GRANTS 的输出。











