show grants 不显示角色继承权限,必须用 using 子句显式指定角色名(如 show grants for 'alice'@'%' using 'app_developer');角色是否生效还取决于会话是否激活(需 set role 或默认角色),flush privileges 不影响角色激活状态。

SHOW GRANTS 不显示角色继承的权限,必须加 USING 子句
执行 SHOW GRANTS FOR 'alice'@'%' 只会列出直接授予 alice 的权限语句,哪怕她已被赋予 app_developer 角色且该角色有 SELECT, INSERT ON sales.*,这些也不会出现在输出里。
要看到角色带来的权限,得显式指定角色名:
SHOW GRANTS FOR 'alice'@'%' USING 'app_developer';- 如果用户有多个激活角色,可一次列出:
SHOW GRANTS FOR 'alice'@'%' USING 'app_developer', 'readonly_analyst'; - 注意:
USING后的角色名必须是已存在、且该用户被GRANT过的角色;若角色未激活(SET ROLE未执行),权限仍不生效,但SHOW GRANTS ... USING仍能查到
查角色继承链要用 mysql.role_edges 表
MySQL 8.0+ 把“谁属于哪个角色”记录在 mysql.role_edges 表中,字段 FROM_HOST/FROM_USER 是角色名,TO_HOST/TO_USER 是被赋角色的用户或另一角色(支持角色嵌套)。
想确认 'alice'@'%' 是否通过角色间接获得 SUPER 权限,不能只查 mysql.user,得顺藤摸瓜:
- 先查她有哪些角色:
SELECT FROM_USER, FROM_HOST FROM mysql.role_edges WHERE TO_USER = 'alice' AND TO_HOST = '%'; - 再查这些角色本身是否被其他角色授予(嵌套):
SELECT * FROM mysql.role_edges WHERE FROM_USER = 'app_developer'; - 最后查角色自身的权限:
SHOW GRANTS FOR 'app_developer'@'%';或查mysql.role_edges关联的mysql.db/mysql.tables_priv
权限叠加时,列级 + 表级 + 角色权限不会自动合并显示
一个用户可能同时满足以下条件:
- 直接被授予
UPDATE(col_a)列权限(存于INFORMATION_SCHEMA.COLUMN_PRIVILEGES) - 所属角色有
UPDATE ON sales.orders(表级,存于INFORMATION_SCHEMA.TABLE_PRIVILEGES) - 全局权限字段
mysql.user.Update_priv = 'Y'
但 SHOW GRANTS FOR 'u'@'h' 只反映第一项(直接授权),其余两项需分别查系统表。更麻烦的是:MySQL 不做“权限求并集”展示,你得自己判断哪一层实际起效——优先级是:列级 > 表级 > 库级 > 全局。
常见误判点:
- 查
INFORMATION_SCHEMA.TABLE_PRIVILEGES发现没UPDATE,就断定不能改表 → 忘了用户可能有更高层级的全局Update_priv='Y' - 看到
SHOW GRANTS里有UPDATE ON sales.*,就以为能改任意列 → 实际上某列被REVOKE UPDATE(col_secret)单独收回了,这只会体现在COLUMN_PRIVILEGES里
FLUSH PRIVILEGES 不刷新角色激活状态
FLUSH PRIVILEGES 只重载磁盘权限表到内存,不影响角色是否激活。用户登录后默认不激活任何角色,除非设置了 SET DEFAULT ROLE 或手动执行 SET ROLE。
这意味着:
- 即使你刚用
GRANT 'app_developer' TO 'alice'@'%'赋了角色,SHOW GRANTS FOR 'alice'@'%'依然看不到角色权限 -
SHOW GRANTS FOR 'alice'@'%' USING 'app_developer'能查到,但此时 alice 实际连接中并未启用它,执行UPDATE仍会报错 - 验证是否真生效,最简单方式是让该用户重新登录,或在其会话中运行:
SET ROLE 'app_developer';再试操作
角色继承关系本身是静态配置,但“是否可用”取决于会话状态——这点容易被忽略,排查时务必区分“授了没”和“用了没”。











