create role创建的角色是空容器,需显式授权、绑定用户、激活三步缺一不可;角色不继承权限、不支持嵌套或列级授权,且show grants默认不显示角色权限。

CREATE ROLE 创建的角色默认不带任何权限,也不自动绑定或激活——它就是一个空容器。你必须显式填充权限、分配给用户、再激活,三步缺一不可。
角色创建后必须用 GRANT 显式授予权限
角色不是“权限模板”,不会继承创建者权限,也不支持列级或行级授权(GRANT SELECT(col1) 在角色上会报错)。常见错误是建完就试用:CREATE ROLE 'reporter'; SET ROLE 'reporter';,立刻触发 ERROR 3530 (HY000): Access denied for user to set role 'reporter'。
-
GRANT SELECT, INSERT ON sales.* TO 'reporter';—— 这是对角色授权,对象是角色名(带单引号) - 系统级权限可以授给角色:
GRANT CREATE, DROP ON *.* TO 'devops_role';,但不能加WITH GRANT OPTION(否则报错ERROR 3529) - 角色名含特殊字符(如
-或.)必须用反引号:GRANT SELECT ON logs.* TO `ci-pipeline`; - 角色不支持嵌套,
GRANT r2 TO r1是非法语法
GRANT 'role_name' TO 'user' 只是绑定,不等于生效
执行 GRANT 'reporter' TO 'ana'@'%'; 后,ana 登录仍无任何权限。这是因为 MySQL 的角色模型严格区分「绑定」和「激活」。
- 必须额外执行
SET DEFAULT ROLE 'reporter' TO 'ana'@'%';,才能让该用户每次连接自动启用角色 - 或者管理员开启全局开关:
SET GLOBAL activate_all_roles_on_login = ON;(注意:这会影响所有新连接,且需 SUPER 权限) - 用户自己执行
SET ROLE 'reporter';需要ROLE_ADMIN权限,或被显式代理:GRANT PROXY ON 'reporter' TO 'ana'@'%'; - 一个用户可被授予多个角色,但
SET DEFAULT ROLE ALL会一次性激活全部,违背最小权限原则,慎用
SHOW GRANTS 默认不显示角色权限,容易误判配置失败
执行 SHOW GRANTS FOR 'ana'@'%'; 可能只返回空或极简内容,但这不代表权限没配好——MySQL 默认只显示直授权限,不展开角色继承链。
- 查用户绑定了哪些角色:
SELECT * FROM mysql.role_edges WHERE to_user = 'ana' AND to_host = '%'; - 查角色带来的真实权限:
SHOW GRANTS FOR 'ana'@'%' USING 'reporter'; - 确认当前会话是否激活:
SELECT CURRENT_ROLE();返回NULL就说明角色根本没生效 -
SHOW GRANTS FOR 'reporter';可直接查看该角色被授予了哪些权限
权限回收和变更要注意 WITH ADMIN OPTION 和 WITH GRANT OPTION 的区别
给角色赋权时,WITH GRANT OPTION 是无效的(会报错),真正控制角色分发权的是 WITH ADMIN OPTION。
-
GRANT SELECT ON app.* TO 'reporter' WITH ADMIN OPTION;→ 允许reporter把「角色本身」再授予其他用户 -
GRANT SELECT ON app.* TO 'reporter' WITH GRANT OPTION;→ MySQL 8.0 禁止,报错ERROR 3529 - 撤销角色权限用
REVOKE SELECT ON app.* FROM 'reporter';,所有绑定该角色的用户会实时失去该权限 - 删除角色前必须先解除用户绑定:
REVOKE 'reporter' FROM 'ana'@'%';,否则DROP ROLE会失败
最常被跳过的环节不是语法写错,而是漏掉 SET DEFAULT ROLE 或忘了在 SHOW GRANTS 后加 USING 子句——这两处不填,整个流程就卡在“看起来配好了,实际完全没用”。











