show grants仅显示显式授予的权限,不包含角色继承、隐式权限或缓存未刷新导致的权限差异,需结合mysql.user、mysql.db、mysql.role_edges等系统表及flush privileges确认真实权限。

SHOW GRANTS 为什么只显示部分权限
执行 SHOW GRANTS FOR 'username'@'host' 返回的只是该用户「显式授予」的权限语句,不包含角色继承来的权限(MySQL 8.0+ 启用角色后常见)。比如用户被赋予了 analyst 角色,但没执行 SET ROLE 'analyst',那角色里定义的 SELECT、EXECUTE 等权限就不会出现在 SHOW GRANTS 输出里。
常见错误现象:你确认已给用户绑定了角色,SHOW GRANTS 却没看到对应库表权限——大概率是角色未激活,或没查 mysql.role_edges 表确认绑定关系。
- 必须严格匹配
'username'@'host'格式,'user'@'localhost'和'user'@'127.0.0.1'是两个不同账号 - 若提示
ERROR 1141 (42000): There is no such grant defined for user,先查SELECT User, Host FROM mysql.user;确认注册账号全貌 - 没有
SELECT权限访问mysql库时,SHOW GRANTS FOR ...会直接失败,而SHOW GRANTS(无参数)仍可用
怎么查清一个用户实际能干啥:全局 + 库级 + 角色权限三合一
单靠 SHOW GRANTS 容易误判,尤其当权限分散在 mysql.user(全局)、mysql.db(库级)、mysql.role_edges(角色)多个地方时。真实生效权限是这些来源的并集。
推荐组合查询(需有 SELECT 权限访问系统表):
SELECT u.User, u.Host, u.Select_priv AS global_select, d.Db, d.Select_priv AS db_select, r.Role, r.From_host FROM mysql.user u LEFT JOIN mysql.db d ON u.User = d.User AND u.Host = d.Host LEFT JOIN mysql.role_edges r ON u.User = r.To_user AND u.Host = r.To_host WHERE u.User = 'app' AND u.Host = '%';
-
global_select = 'Y'表示全局可查任意库;db_select = 'Y'表示仅对d.Db库有查权限 - 若
r.Role非空,说明该用户绑定了角色,需进一步查mysql.roles_mapping或对应角色的SHOW GRANTS FOR ROLE 'xxx' - 查完记得确认是否执行过
FLUSH PRIVILEGES,否则内存缓存可能滞后于磁盘配置
mysqlshow 是最轻量的权限试探工具
不进 MySQL 客户端也能快速验证权限边界:mysqlshow 命令本质是用目标用户身份尝试执行 SHOW DATABASES 和 SHOW TABLES,比写 SQL 更快暴露问题。
例如:
mysqlshow -u app -p -h 10.0.1.5
- 若报
Access denied for user 'app'@'10.0.1.5'→ 连认证都没过,或 host 不匹配 - 若列出数据库但进某库时报
ERROR 1142 (42000): SHOW command denied→ 有库访问权,但缺SHOW VIEW或对应库的SELECT权限 - 若能进库但
SHOW TABLES为空 → 可能表名大小写不一致(Linux 下lower_case_table_names=0),或权限只给了视图没给基表
权限“看得见却用不了”的典型原因
即使 SHOW GRANTS 显示有 SELECT ON mydb.*,执行 SELECT * FROM mydb.users 仍可能报错,关键不在授权语句本身,而在上下文约束。
- 目标库
mydb未出现在该用户的mysql.db记录中(即只有全局权限,没单独授库级权限) - 表名大小写和授权时不一致:比如授权的是
USERS,但代码里写了users,Linux 环境下会拒绝 - 查询涉及视图或函数,但用户缺少
EXECUTE权限,或视图定义中引用的基表用户无SELECT权限 - 启用了
sql_mode=STRICT_TRANS_TABLES等严格模式,导致隐式权限校验更苛刻
真正卡住的地方往往不是“有没有权限”,而是“权限作用域是否覆盖当前操作路径”——查 SHOW GRANTS 只是起点,得顺着 user → db → tables_priv → role_edges 一层层核对生效范围。











