MySQL 8.0中角色需显式激活才能生效,GRANT仅绑定角色与用户,必须通过SET DEFAULT ROLE或activate_all_roles_on_login=ON配置并重新登录;SHOW GRANTS不显示角色权限属正常设计,应使用SHOW GRANTS ... USING验证。

角色没激活,不是权限没授对
MySQL 8.0 中执行 GRANT 'app_reader' TO 'user1'@'%' 只是把角色和用户绑定了,mysql.role_edges 表里多了一条记录,但登录后 CURRENT_ROLE() 返回 NONE,说明角色压根没加载进当前会话。这不是授权语句写错了,而是激活环节缺失——MySQL 默认不自动激活任何角色。
必须显式设置默认角色或启用全局自动激活
用户登录后权限不可用,核心就卡在这一步:
- 若想单用户生效:用高权限账号执行
SET DEFAULT ROLE 'app_reader' TO 'user1'@'%'(注意 host 必须完全匹配,'app_reader'@'%'不能配给'user1'@'localhost') - 若想所有用户统一行为:设
activate_all_roles_on_login=ON,但必须写进my.cnf的[mysqld]段,并重启 MySQL;仅SET GLOBAL是临时的,且只影响新连接 - 执行完任一方式后,必须让目标用户重新登录,已有连接不会刷新角色状态
SHOW GRANTS 不显示角色权限是正常设计
执行 SHOW GRANTS FOR 'user1'@'%' 看到的只有直授权限,比如 USAGE ON *.* 和 GRANT 'app_reader'@'%' TO 'user1'@'%',这不代表权限没生效——这是 MySQL 的明确设计,不是配置失败。
要验证角色是否真带来权限,得用:
-
SHOW GRANTS FOR 'user1'@'%' USING 'app_reader'—— 查看该角色实际赋予了哪些权限 -
SELECT CURRENT_ROLE()—— 登录后执行,返回非NONE才算激活成功 - 真实跑一句
SELECT * FROM myapp.users LIMIT 1—— 别信元数据,只信执行结果
activate_all_roles_on_login=ON 和 SET DEFAULT ROLE 互斥
这两个机制不能共存,而且是单向覆盖:
- 一旦
activate_all_roles_on_login=ON生效,SET DEFAULT ROLE就完全失效,所有已授予的角色都会在登录时全部激活 - 如果你依赖最小权限原则(比如只希望用户默认激活
r_ro,而非r_ro+r_rw),就必须保持activate_all_roles_on_login=OFF(即默认值) - 误设为
ON后再执行SET DEFAULT ROLE不报错,但CURRENT_ROLE()查不到变化,权限实际由全部已授角色叠加决定
最容易被忽略的是:角色名大小写敏感、CREATE ROLE 后必须先 GRANT 权限给角色本身、activate_all_roles_on_login 从 8.0.2 才支持——低于这个版本设了也白设。











