INFORMATION_SCHEMA.APPLICABLE_ROLES 是查看当前会话已激活角色的唯一准确视图,每行代表一个显式激活的角色,含 ROLE_NAME、ROLE_HOST、IS_GRANTABLE 字段,且仅对当前连接有效。

直接查 INFORMATION_SCHEMA.APPLICABLE_ROLES,这是唯一能准确反映「当前会话已激活角色」的系统视图;CURRENT_ROLE() 返回字符串,IS_ROLE_ENABLED() 只能单点判断,都不适合“查看所有”这个需求。
为什么 APPLICABLE_ROLES 是首选
该视图专为角色激活状态设计,每行代表一个当前会话中处于激活态的角色,字段清晰、无歧义:
-
ROLE_NAME:角色名(不含主机部分,如'report_role') -
ROLE_HOST:角色绑定的主机(如'%'或'localhost') -
IS_GRANTABLE:是否具有WITH ADMIN OPTION(即能否再授出该角色) - 只返回显式激活的角色,不包含隐式继承或未执行
SET ROLE的角色
执行 SELECT * FROM INFORMATION_SCHEMA.APPLICABLE_ROLES; 即可获得完整列表。注意:它只对当前连接有效,不同会话结果可能不同。
CURRENT_ROLE() 返回 NULL 或空字符串的常见原因
这不是 bug,而是行为符合预期——它只在显式激活后才有值:
- 登录后未执行任何
SET ROLE→ 返回NULL - 执行过
SET ROLE NONE→ 返回空字符串'' - 执行过
SET ROLE 'r1', 'r2';→ 返回'r1@%,r2@%'(含主机名,逗号分隔) - 即使用户被授予了角色,且
activate_all_roles_on_login = ON,也必须是新连接才生效;已有会话仍需手动SET ROLE
别用它做“是否有激活角色”的布尔判断——IS_ROLE_ENABLED('xxx') 更可靠,但不适合批量枚举。
如何确认角色确实已被激活(而不仅是被授予)
光看 mysql.role_edges 或 SHOW GRANTS FOR user 不够,那些只说明“有资格”,不等于“已启用”:
- 查授予关系:
SELECT * FROM mysql.role_edges WHERE TO_USER = 'your_user' AND TO_HOST = '%'; - 查当前激活:
SELECT * FROM INFORMATION_SCHEMA.APPLICABLE_ROLES; - 查默认角色设置:
SELECT * FROM mysql.default_roles WHERE USER = 'your_user' AND HOST = '%'; - 查全局配置:
SELECT @@global.activate_all_roles_on_login;—— 若为OFF(默认),则新连接也不会自动激活
三者全为真,才表示角色既被授予、又被正确激活。漏掉任一环,权限都不可用。
最易被忽略的是:角色激活状态完全独立于用户登录认证,它只依赖会话生命周期和显式指令;没有“后台自动同步”机制,也没有跨会话缓存——每次连接都要重新确认。


















