mysql 8.0角色权限生效需严格四步:启用activate_all_roles_on_login、create role、grant权限给角色、grant角色并set default role激活用户;缺一不可,否则current_role()返回null且权限不生效。

CREATE ROLE 和 GRANT 是 MySQL 8.0 角色管理的两个核心操作,但光执行这两条语句,权限绝不会自动生效。角色不是“创建即可用”的快捷方式,而是一套必须严格按序执行的四步链:启用支持 → 创建角色 → 授权给角色 → 授予并激活角色给用户。
CREATE ROLE 前必须确认 activate_all_roles_on_login 已启用
MySQL 8.0 默认关闭角色功能,即使语法能解析,CREATE ROLE 也会失败或后续授权静默失效。
- 执行
CREATE ROLE 'app_reader'报错ERROR 3719 (HY000): 'role_admin'@'%' is not set as a role,本质是缺失全局开关和管理员权限。 - 必须由高权限用户(如
root)先运行:SET GLOBAL activate_all_roles_on_login = ON;
GRANT ROLE_ADMIN ON *.* TO 'admin_user'@'%';
FLUSH PRIVILEGES;
- 该变量重启失效,生产环境务必写入
my.cnf:[mysqld] activate_all_roles_on_login=ON
不走这步,所有角色操作都停留在“语法正确、行为无效”状态。
GRANT 授权对象必须明确区分“授给谁”
角色权限 ≠ 用户权限,GRANT 的目标主体决定权限归属层级,混淆就会导致权限不可见、不可用。
- 给角色授予权限(正确):
GRANT SELECT ON myapp.* TO 'app_reader'@'%';
- 给用户授予权限(绕过角色,不推荐批量管理):
GRANT SELECT ON myapp.* TO 'user1'@'%';
- 把角色授予用户(绑定关系,非激活):
GRANT 'app_reader'@'%' TO 'user1'@'10.20.%';
常见错误:
- 省略主机名:
GRANT SELECT ON db.* TO 'app_reader'实际等价于'app_reader'@'%',但后续GRANT 'app_reader' TO 'user1'@'localhost'会因主机不匹配失败; - 对角色使用
WITH GRANT OPTION:MySQL 8.0 明确禁止,报错ERROR 3526 (HY000); - 在角色上尝试列级授权(如
GRANT SELECT(col1) ON t1 TO 'r'):直接报错ERROR 1142,角色不支持列级粒度。
SHOW GRANTS 查不到角色权限?必须加 USING 或查系统表
用户执行 SHOW GRANTS FOR 'user1'@'%' 返回空或只有 USAGE,不等于权限没配好——这是 MySQL 的默认行为:它只显示直接授予用户的权限,不展开角色继承链。
- 查用户被授予了哪些角色:
SELECT * FROM mysql.role_edges WHERE to_user = 'user1' AND to_host = '%';
- 查角色本身有哪些权限:
SHOW GRANTS FOR 'app_reader'@'%';
- 查用户在某角色上下文中的实际权限:
SHOW GRANTS FOR 'user1'@'%' USING 'app_reader'@'%';
- 验证当前会话是否激活:
SELECT CURRENT_ROLE();
返回NULL就说明角色未激活,哪怕已GRANT绑定。
跳过这些验证步骤,容易把“流程漏步”误判为“配置失败”。
SET DEFAULT ROLE 是权限真正生效的临门一脚
GRANT 'app_reader'@'%' TO 'user1'@'10.20.%' 只是建立映射关系,不触发任何权限加载。用户登录后仍处于无角色状态。
- 激活单个角色(推荐,符合最小权限):
SET DEFAULT ROLE 'app_reader'@'%' TO 'user1'@'10.20.%';
- 激活所有已授予角色(慎用):
SET DEFAULT ROLE ALL TO 'user1'@'10.20.%';
- 前提硬性条件(缺一不可):
- 执行者有
ROLE_ADMIN权限; - 目标角色已通过
GRANT ... TO role_name显式赋权; - 用户账户已存在(哪怕只有
USAGE); - 执行后需
FLUSH PRIVILEGES(部分版本要求)。
- 执行者有
没这步,CURRENT_ROLE() 永远是 NULL,应用连不上库或报 Access denied 都是必然结果。
角色管理真正的复杂点不在语法,而在四步之间的依赖性和不可跳过性:启用、创建、授权、激活,环环相扣。任意一步省略或顺序错乱,都会让权限停留在“纸面有效、运行失效”状态。











