直接执行show grants可查看当前用户全部显式权限,它自动聚合全局、库、表等层级权限并输出可执行grant语句;查他人权限须严格指定'username'@'host'格式,否则报错error 1141。

直接查 mysql.user 表只能看到全局权限,不全
MySQL 的权限分层级(全局、库、表、列、存储过程等),mysql.user 表只存了 SELECT_priv、Insert_priv 这类全局开关,但用户很可能在某个库上被单独授过 GRANT SELECT ON db1.* TO 'u1'@'%' —— 这类细粒度权限存在 mysql.db、mysql.tables_priv 等表里,直接查 user 表会漏掉绝大部分实际权限。
真正可靠的方式是用 SHOW GRANTS,它自动聚合所有层级的权限并还原成可执行的 GRANT 语句:
SHOW GRANTS FOR 'username'@'host';
注意必须带主机名(哪怕只是 'localhost'),否则报错 ERROR 1141 (42000): There is no such grant defined for user 'xxx' on host '%'。
SHOW GRANTS 返回结果怎么读?
输出是多行 GRANT ... 语句,每条对应一个权限范围。例如:
GRANT USAGE ON *.* TO 'app_user'@'10.0.1.%'<br>GRANT SELECT, INSERT ON `orders`.* TO 'app_user'@'10.0.1.%'<br>GRANT SELECT ON `reports`.`summary` TO 'app_user'@'10.0.1.%'
关键点:
-
USAGE表示“仅登录权限”,没实际操作权 -
ON *.*是全局权限(如CREATE USER) -
ON `db`.*是数据库级权限 -
ON `db`.`table`是表级权限,已精确到对象
如果用户有同名但不同 host 的账号(比如 'u1'@'localhost' 和 'u1'@'%'),MySQL 按 host 匹配规则选最具体的那个,SHOW GRANTS 只显示匹配到的那个账号的权限。
想导出所有用户的权限做审计?别硬扫系统表
有人会想写 SQL 联查 mysql.user + mysql.db + mysql.tables_priv… 这不仅逻辑复杂(权限合并规则要自己实现),还容易漏掉列权限、动态权限(如 BACKUP_ADMIN)、角色绑定权限。
更稳妥的做法是批量执行 SHOW GRANTS:
SELECT CONCAT('SHOW GRANTS FOR ''', User, '''@''', Host, ''';') FROM mysql.user;
把结果复制进客户端逐条执行,或用脚本(如 Python + pymysql)循环调用。注意:普通用户无法查 mysql.user 表,必须用 root 或有 SELECT 权限的账号。
遇到 Access denied 却查不到对应 GRANT?检查角色和动态权限
MySQL 8.0+ 引入角色(ROLE)和动态权限(如 SYSTEM_VARIABLES_ADMIN),它们不会出现在 SHOW GRANTS 的主输出里:
- 角色权限需额外查:
SHOW GRANTS FOR 'u1'@'h1' USING 'role_name'; - 动态权限需查:
SELECT * FROM mysql.role_edges WHERE TO_HOST = 'u1'@'h1';和SELECT * FROM mysql.role_edges WHERE FROM_HOST = 'role_name'; - 当前会话生效的权限可用:
SELECT * FROM performance_schema.role_table_grants;(需开启相关 instruments)
权限叠加规则复杂,SHOW GRANTS 只展示显式授予的语句,不反映最终生效效果 —— 实际能否执行某操作,还得看 SELECT CURRENT_ROLE() 和 SHOW GRANTS 组合判断。











