角色需用grant role显式授予用户,如grant 'analyst' to 'alice'@'localhost';新用户须set default role或set role激活,且activate_all_roles_on_login默认关闭;角色可嵌套但限单层;权限回收须针对角色或解绑,不可对用户直 revoke。

角色怎么赋给用户:用 GRANT ROLE 而不是 GRANT
MySQL 8.0+ 的 RBAC 权限模型里,角色和用户是两个独立实体,不能像旧版那样直接把权限塞给用户。必须显式绑定——用 GRANT ROLE 把角色授予用户,否则角色里的权限对用户完全无效。
常见错误现象:SELECT CURRENT_ROLE() 返回 NULL,或执行带权限的语句报 ERROR 1045 (28000): Access denied,往往是因为只创建了角色、没真正授给用户。
-
CREATE ROLE 'analyst';和GRANT SELECT ON sales.* TO 'analyst';只是定义了角色权限,不作用于任何人 - 必须补上:
GRANT 'analyst' TO 'alice'@'localhost'; - 新用户默认不激活角色,需执行
SET ROLE 'analyst';或设为默认:SET DEFAULT ROLE 'analyst' TO 'alice'@'localhost';
角色权限不生效?检查 activate_all_roles_on_login 配置
即使 GRANT ROLE 成功,用户登录后角色默认不自动激活(除非显式 SET ROLE)。这是最常被忽略的环节,尤其在应用连接池场景下容易误判为权限配置失败。
影响范围:所有 MySQL 8.0.x 默认安装(该变量默认为 OFF),Docker 镜像、云数据库 RDS 也普遍沿用此行为。
- 临时启用(当前会话):
SET ROLE ALL; - 全局开启(需 SUPER 权限):
SET PERSIST activate_all_roles_on_login = ON; - 更稳妥的做法是在用户创建时设默认角色:
ALTER USER 'bob'@'%' DEFAULT ROLE 'reporter';
角色嵌套是否支持:可以,但层级不能过深
MySQL 允许角色 A 授予角色 B(即角色继承),但仅支持单层间接引用。超过两层嵌套(比如 role_A → role_B → role_C)会导致 SET ROLE 失败并报错 ERROR 3530 (HY000): Cannot set role 'role_A' because it contains a circular or too-deep role hierarchy。
实际使用中建议扁平化设计:一个业务角色直接聚合所需权限,避免用“角色套角色”模拟组织架构。
- 允许:
GRANT 'editor' TO 'publisher';(publisher 拥有 editor 权限) - 禁止:
GRANT 'admin' TO 'super_editor'; GRANT 'super_editor' TO 'publisher';(两层嵌套已到极限,再加一层就触发报错) - 查看依赖链:
SELECT * FROM mysql.role_edges WHERE TO_HOST = '%';
权限回收时,REVOKE 用户还是 REVOKE 角色?
权限回收必须作用于「授权路径」的终点。如果权限来自角色,则不能对用户 REVOKE SELECT ON db.* FROM 'user'@'host' —— 这条语句无效,因为用户本身没被直接授权,只是通过角色间接获得。
正确做法是:要么从角色上收回权限(影响所有拥有该角色的用户),要么把角色从用户身上撤掉。
- 批量调整:修改角色定义,
REVOKE INSERT ON logs.* FROM 'writer'; - 单用户隔离:取消绑定,
REVOKE 'writer' FROM 'carol'@'10.%'; - 注意:
DROP ROLE 'writer';会级联清除所有绑定关系,但不会删用户,也不会清空用户自身直接持有的权限
RBAC 的核心约束在于:权限只存在于角色定义或用户直授中,中间没有“继承副本”。改角色就是改所有使用者的权限视图,这点和操作系统组权限逻辑一致,但比 Linux group 更严格——没有 uid/gid 映射缓存,每次权限检查都实时解析角色边。











