mysql 8.0 的 create role 必须严格遵循创建→授权→分配→激活四步闭环,缺一不可;否则 current_role() 返回 null,权限不生效。需先启用角色支持(set global activate_all_roles_on_login = on 并 grant role_admin),再显式授权、绑定用户、设置默认角色。

MySQL 8.0 的 CREATE ROLE 不是“建完就能用”,必须走完创建 → 授权 → 分配 → 激活四步闭环,漏任一步 CURRENT_ROLE() 返回 NULL,权限实际不生效。
CREATE ROLE 报 ERROR 1064 或 ERROR 3719 怎么办
ERROR 1064 几乎一定是版本问题:执行 SELECT VERSION();,输出低于 8.0.1 就别试了,5.7 及更早压根不支持角色语法。
ERROR 3719('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;
注意:activate_all_roles_on_login 是动态变量,重启失效;要持久化,得在 my.cnf 的 [mysqld] 段加 activate_all_roles_on_login=ON。
GRANT 权限给角色 ≠ 用户能用,两步不能合并
常见错误是建完 'app_reader' 就急着 GRANT 'app_reader' TO 'user1'@'%',结果用户登录后仍报 ERROR 1142 (42000): SELECT command denied。
真正要分清:
-
GRANT SELECT ON myapp.* TO 'app_reader'@'%';—— 给角色“装权限”,角色本身没连接能力,只是容器 -
GRANT 'app_reader'@'%' TO 'user1'@'%';—— 把角色“挂载”到用户,但不激活
角色名务必带主机名(如 'app_reader'@'%'),否则后续匹配失败;列级授权(GRANT SELECT(id) ON t1 TO r1)会直接报错,不支持。
SET DEFAULT ROLE 是权限生效的临门一脚
用户被授予角色后,SHOW GRANTS FOR 'user1'@'%' 只显示 GRANT 'app_reader'@'%' TO ...,**不会展开角色内权限**——这是设计如此,不是配置失败。
真正验证是否生效,必须用目标用户登录后执行:
-
SELECT CURRENT_ROLE();—— 返回非NULL值才算激活成功 - 若返回
NULL,大概率卡在没执行SET DEFAULT ROLE 'app_reader'@'%' TO 'user1'@'%';
该语句需由有 ROLE_ADMIN 或 SYSTEM_VARIABLES_ADMIN 权限的管理员执行;普通用户无法自设。连接池场景(如 HikariCP)默认不执行初始化 SQL,需显式配 connection-init-sql="SET DEFAULT ROLE 'app_reader'"。
REVOKE 和 SHOW GRANTS 容易误判权限范围
SHOW GRANTS FOR 'user1'@'%' 看不到角色权限,容易误以为没配好。要查角色本身有哪些权限,得用:
SHOW GRANTS FOR 'app_reader'@'%';- 或查继承关系:
SHOW GRANTS FOR 'user1'@'%' USING 'app_reader'@'%';
回收权限时,FROM 后的对象决定影响范围:
-
REVOKE SELECT ON myapp.* FROM 'app_reader'@'%';—— 所有通过该角色获得 SELECT 的用户立刻失效 -
REVOKE 'app_reader'@'%' FROM 'user1'@'%';—— 只影响这个用户,不影响角色定义和其他人
输错一个字符(比如把角色名写成用户名),要么收不干净,要么收过头——生产环境改前务必核对 FROM 后是角色还是用户。











