mysql 8.0角色是空权限容器,必须先grant授权、再grant给用户、最后通过set default role或activate_all_roles_on_login激活才生效;否则用户登录后无权限。

MySQL 8.0 的角色不是“自动生效”的,必须显式激活才能起作用;不设 DEFAULT ROLE 或不开 activate_all_roles_on_login,用户登录后权限是空的。
CREATE ROLE 后权限为零,必须用 GRANT 显式授权
刚创建的角色(如 CREATE ROLE 'analyst')在 mysql.role_edges 表里只有记录,但 mysql.tables_priv、mysql.db 等权限表中查不到任何条目。它本质是个空容器。
- 必须执行类似
GRANT SELECT ON sales.* TO 'analyst'才真正赋予权限 - 角色可被重复
GRANT多次,权限会叠加(无去重逻辑) - 对角色执行
SHOW GRANTS FOR 'analyst'才能看到实际分配了哪些权限 - 误以为“建了角色就等于有权限”,是新手最常踩的坑
用户拿到角色 ≠ 当前会话能用,SET DEFAULT ROLE 是关键一步
即使你已执行 GRANT 'analyst' TO 'dev_user'@'%',dev_user 登录后执行 SELECT * FROM sales.orders 仍会报 ERROR 1142 (42000): SELECT command denied —— 因为角色未激活。
- 激活方式一(推荐):
ALTER USER 'dev_user'@'%' DEFAULT ROLE 'analyst',下次登录即生效 - 激活方式二(临时):
SET ROLE 'analyst',仅对当前连接有效,断开重连即失效 - 激活方式三(全局开关):
SET PERSIST activate_all_roles_on_login = ON,所有用户登录时自动激活所有已授予角色 - 注意:
DEFAULT ROLE必须是用户已被GRANT过的角色,否则报错ERROR 3530 (HY000): Access denied for user ... to role ...
mandatory_roles 是隐形强制项,改配置前务必确认影响范围
如果你在 my.cnf 中设置了 mandatory_roles = 'auditor'@'%',或运行了 SET PERSIST mandatory_roles = '''auditor''@''%''' ,那所有用户(包括 root)登录时都会强制获得该角色权限,且无法 REVOKE 或 DROP ROLE 删除它。
- 强制角色不显示在
SHOW GRANTS FOR user结果中,但会出现在CURRENT_ROLE()返回值里 - 它绕过常规授权链路,属于“预加载权限”,适合审计类只读账号统一管控
- 修改
mandatory_roles后,已有连接不受影响,新连接才生效 - 删除强制角色只能通过
SET PERSIST mandatory_roles = ''清空,不能用DROP ROLE
查看当前会话真实生效的角色:别只信 SHOW GRANTS
SHOW GRANTS FOR 'user' 只显示“被授予了哪些角色”,不反映“当前激活了哪些”。真正决定权限的是会话级状态。
- 查当前激活角色:
SELECT CURRENT_ROLE()(返回字符串,如'analyst')或SHOW ACTIVE ROLES(返回结果集) - 查用户默认角色:
SELECT * FROM mysql.default_roles WHERE USER = 'dev_user' AND HOST = '%' - 查角色与用户的绑定关系:
SELECT * FROM mysql.role_edges WHERE TO_HOST = '%' AND TO_USER = 'dev_user' - 权限冲突时(比如两个角色都授了
INSERT但一个又REVOKEd),以最后执行的语句为准,MySQL 不做逻辑合并
RBAC 在 MySQL 8.0 里不是开箱即用的抽象层,而是一套需要精确控制激活时机、作用域和持久化方式的机制。最容易被忽略的是:角色权限只在激活后才参与访问检查,而激活本身依赖于用户级配置、全局变量、甚至 my.cnf 的静态设定 —— 三者任意一处漏配,整个 RBAC 链就断了。











