MySQL 8.0+才支持CREATE ROLE角色管理,5.7及以下需用传统GRANT逐用户授权;角色是纯权限容器,不可登录,须先建角色、赋权、再绑定用户,并显式激活;权限回收须先解绑、再撤权、最后删角色。

创建角色前先确认 MySQL 版本是否支持
MySQL 8.0 才正式引入 CREATE ROLE 和角色管理语法,5.7 及更早版本不支持——强行执行会报错 ERROR 1064 (42000)。别在测试环境用 8.0 写完脚本,上线发现生产库是 5.7 就全卡住。
检查方法很简单:SELECT VERSION();。如果低于 8.0,只能退回到传统用户粒度授权(GRANT ... ON db.table TO 'user'@'host'),没法用角色做中间抽象层。
- 8.0+:可建角色、分配权限、再把角色赋给用户,权限变更只需动角色
- 5.7 及以下:每个开发者账号得单独
GRANT,改权限要逐个更新,易漏、难审计
用 CREATE ROLE 和 GRANT 分离权限定义与人员绑定
角色不是用户,它不登录、没密码、不能连库,纯粹是权限容器。常见错误是直接对角色执行 CREATE USER 或试图用角色名连数据库。
正确流程分三步:
- 建角色:
CREATE ROLE 'dev_readonly'; - 赋权限:
GRANT SELECT ON `app_%`.* TO 'dev_readonly';(注意反引号包裹通配库名) - 绑用户:
GRANT 'dev_readonly' TO 'alice'@'%';,之后还要FLUSH PRIVILEGES;或者用SET DEFAULT ROLE激活
别漏掉最后一步:新绑定的角色默认不生效,用户下次登录才自动激活;如需立即生效,得显式执行 SET ROLE 'dev_readonly'; 或 SET DEFAULT ROLE ALL TO 'alice'@'%';
慎用 USAGE 权限和通配符库名
USAGE 看似“啥也不给”,其实它允许用户连接成功(只要密码对),常被误当“禁用账号”用——结果开发者能连上但执行任何语句都报 ERROR 1044 (42000):Access denied for user,排查时容易绕弯。
通配符库名(如 app_%)方便管理多环境库(app_dev、app_staging),但有坑:
- 匹配只发生在 GRANT 时刻,新建的
app_prod不会自动获得权限,得手动补GRANT ... ON app_prod.* - 如果开发库名含下划线(如
my_app_v2),my\_app%才能精确匹配,my_app%会错失 -
*表示所有当前存在的库,不包含未来新建的;*.*是全局,别乱授
权限回收必须用 REVOKE + DROP ROLE 配合
删角色前不回收权限,会导致已绑定该角色的用户权限残留——MySQL 不会自动清理。比如你 DROP ROLE 'dev_readonly'; 后,alice 仍保有之前通过该角色获得的 SELECT 权,直到她重连或你手动 REVOKE。
安全回收步骤:
- 先解绑:
REVOKE 'dev_readonly' FROM 'alice'@'%'; - 再清权限:
REVOKE SELECT ON `app_%`.* FROM 'dev_readonly'; - 最后删角色:
DROP ROLE 'dev_readonly';
如果角色已被多人使用,REVOKE 用户侧角色比逐个 REVOKE 权限更轻量;但一旦角色本身权限变了,所有绑定用户都会同步变化——这点灵活,也危险。
最麻烦的是跨库权限依赖:比如某个角色同时有 app_core.* 的 SELECT 和 logs.* 的 INSERT,而你只想收回写日志权限。这时候不能只删角色,得拆成两个角色,否则一动全动。











