current_role() 返回空字符串表示当前会话未激活任何角色,而非函数失效;它仅显示最新激活的单个角色名,不反映已授予但未启用的角色或角色继承关系。

CURRENT_ROLE() 返回空字符串,不是函数失效,而是当前会话没激活任何角色。 它只反映「此刻生效的角色」,不展示已授予但未启用的、也不列出多个——哪怕你 SET ROLE ALL,它也只返回最后一个被激活的角色名。
为什么 SELECT CURRENT_ROLE(); 总是返回空字符串
常见错误是以为 GRANT 角色给用户后权限就自动可用。实际上 MySQL 8.0 默认不激活角色,必须显式触发才能让 CURRENT_ROLE() 返回非空值:
- 用户登录后,即使被
GRANT 'role_x' TO 'u'@'%';过,CURRENT_ROLE()仍为空 - 必须先执行
SET ROLE 'role_x'@'%';或SET DEFAULT ROLE 'role_x'@'%' TO 'u'@'%';才能激活 - 如果用户有多个角色但没设默认角色,又没手动
SET ROLE,那会话始终处于“无活跃角色”状态 -
activate_all_roles_on_login系统变量为 OFF(默认)时,该行为才成立;若为 ON,则登录即全激活,CURRENT_ROLE()不会为空
CURRENT_ROLE() 的实际使用场景和验证链
它真正有用的地方,是在存储过程、中间件或连接池复用场景中,快速确认当前上下文是否已进入预期权限边界:
- 先激活:
SET ROLE 'reporter'@'%'; - 再验证:
SELECT CURRENT_ROLE();→ 应返回'reporter'@'%' - 若需清空当前角色上下文:
SET ROLE NONE;,此时CURRENT_ROLE()又变为空字符串 - 注意:
SET ROLE ALL EXCEPT 'admin'@'%';后,CURRENT_ROLE()依然只返回单个角色名(最新激活的那个),不是列表
查“所有可能角色”不能靠 CURRENT_ROLE(),得换方式
CURRENT_ROLE() 不提供已授予但未激活的角色列表,也不反映角色继承关系。要查用户「有权切换到哪些角色」,必须查系统表:
SELECT * FROM information_schema.APPLICABLE_ROLES
WHERE IS_GRANTABLE = 'YES'
AND GRANTEE = CONCAT('''', USER(), '''@''', SUBSTRING_INDEX(USER(), '@', -1), '''');
这个查询返回的是该用户被显式 GRANT 过、且未被 REVOKE 的角色集合(即“可切换角色池”),但不保证当前 session 生效。它不包含角色内具体权限,要看权限得单独执行 SHOW GRANTS FOR 'role_name'@'%';。
容易忽略的一点:CURRENT_ROLE() 能返回结果,不代表角色权限真能用——你还得确认该角色本身已被授予权限、用户有 ROLE_ADMIN 或对应 WITH ADMIN OPTION 权限来激活它,且客户端协议版本 ≥ 8.0.11。否则看起来一切正常,实际 SELECT 表仍报错 Access denied。











