mysql 8.0 的 create role 必须完成创建→授权→分配→激活四步闭环才生效,缺一即导致 current_role() 返回 null;error 1064 表明版本低于 8.0.1,error 3719 则因未启用 activate_all_roles_on_login 或缺失 role_admin 权限。

MySQL 8.0 的 CREATE ROLE 不是建完就能用,必须走完「创建 → 授权 → 分配 → 激活」四步闭环,漏任一步 CURRENT_ROLE() 就返回 NULL,权限实际不生效。
CREATE ROLE 报 ERROR 1064 或 ERROR 3719 怎么办
这两个错误基本不是语法写错,而是卡在版本或配置上:
-
ERROR 1064:几乎一定是 MySQL 版本太低。执行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'"
SHOW GRANTS 看不到角色权限,不是没配好
这是最容易误判的点:只查 SHOW GRANTS FOR 'user1'@'%',发现没列出 SELECT 就以为权限没授成功。
- 查角色自身权限:
SHOW GRANTS FOR 'app_reader'@'%'; - 查某用户通过某角色获得的权限:
SHOW GRANTS FOR 'user1'@'%' USING 'app_reader'@'%'; - 权限变更后,已存在的会话不会自动更新——必须重连,或手动执行
SET ROLE 'app_reader'@'%'; - 审计时如果只扫
SHOW GRANTS输出,可能把拥有 DBA 权限的账号当成“仅能连接”,风险极大
最常被忽略的是:即使你刚 GRANT SELECT ON new_table TO 'app_reader',已连着的会话仍查不到新表——权限缓存机制决定了它只对新连接或主动 SET ROLE 生效。











