90%角色权限未生效是因角色未激活而非未授予:先确认角色是否绑定(查mysql.role_edges),再检查是否执行set role或设默认角色,最后用show grants for ... using验证权限,注意认证插件、连接上下文及作用域匹配。

角色赋予成功但权限未生效,90% 是因为角色没激活,不是没授、也不是写错了。
确认角色是否已绑定到用户
GRANT 'role_name' TO 'user'@'host'; 只是建立关联,不是“启用”。如果没执行这步,后续所有操作都无效。
- 查绑定关系最直接:运行
SELECT * FROM mysql.role_edges WHERE to_user = 'user' AND to_host = 'host';,结果为空就说明根本没绑上 - 注意角色名也要带 host(如
'analyst'@'%'),GRANT 'analyst' TO 'user'@'localhost'对'user'@'127.0.0.1'无效 - 大小写和空格必须完全一致——
'ANALYST'和'analyst'是两个角色
检查角色是否被激活
绑定 ≠ 激活。MySQL 登录后默认不启用任何角色,CURRENT_ROLE() 返回 NULL 就是铁证。
- 临时启用:
SET ROLE 'role_name';,然后立刻SELECT CURRENT_ROLE();验证 - 永久生效需设默认角色:
ALTER USER 'user'@'host' DEFAULT ROLE 'role_name';(需要ROLE_ADMIN权限) - 全局开关(重启失效):
SET GLOBAL activate_all_roles_on_login = ON;,但必须写进my.cnf的[mysqld]段才持久
验证权限是否真能用,而不是只看 SHOW GRANTS
SHOW GRANTS FOR 'user'@'host'; 默认不显示角色继承的权限,容易误判成功。
- 查角色本身权限:
SHOW GRANTS FOR 'role_name'@'%'; - 查用户通过该角色获得的权限:
SHOW GRANTS FOR 'user'@'host' USING 'role_name';(注意:CURRENT_ROLE()必须非NULL,否则返回空) - 实操测试必须匹配作用域:角色授的是
mydb.*,就得先USE mydb;再SELECT * FROM t;,在其他库下执行照样报错
别忽略认证插件和连接上下文
MySQL 8.0+ 默认用 caching_sha2_password 插件,某些客户端或驱动会静默降级失败,表现为“能登录但权限不对”。
- 确认用户实际认证方式:
SELECT user, host, plugin FROM mysql.user WHERE user = 'user';,若为caching_sha2_password,老版本客户端可能无法正确协商角色上下文 - 应用服务端重连后,角色不会自动恢复——连接池里的旧连接仍处于未激活状态,必须重建连接或显式
SET ROLE - Docker 或云环境要注意:你
GRANT的实例和应用连的实例是不是同一个?SELECT USER(), CURRENT_USER();是唯一可信的身份快照
最容易被跳过的点:角色权限只在当前会话激活后才参与校验,且不跨库生效;SHOW GRANTS 不加 USING 子句时,永远看不到角色带来的权限——这不是 bug,是设计。











