查mysql用户权限应看mysql.user、mysql.db、mysql.tables_priv、mysql.columns_priv及mysql 8.0+的mysql.role_edges和mysql.default_roles共六张表,因权限按全局→数据库→表→列→角色层级分散存储,缺一不可。

查 MySQL 用户权限该看哪几张系统表?
直接查 mysql.user 表只能看到全局权限(比如 SELECT_priv、Insert_priv 这类字段),但实际权限还分散在 mysql.db、mysql.tables_priv、mysql.columns_priv 等表里。漏掉其中任意一张,就可能误判用户到底有没有某张表或某个字段的权限。
最稳妥的方式是组合查询,而不是只盯一张表。尤其要注意:MySQL 8.0+ 默认启用了角色(roles)机制,mysql.role_edges 和 mysql.default_roles 也得纳入检查范围。
-
mysql.user:全局权限 + 账户状态(account_locked)、密码过期策略 -
mysql.db:数据库级权限(Db字段匹配库名,Select_priv等字段为Y/N) -
mysql.tables_priv:表级权限,注意Table_name和Grantor字段 -
mysql.columns_priv:列级权限,Column_name字段区分具体字段
用 SHOW GRANTS 查权限为什么有时不准?
SHOW GRANTS FOR 'user'@'host' 看起来最方便,但它只展示“显式授予”的权限,不反映通过角色继承来的权限(MySQL 8.0+),也不体现因 WITH GRANT OPTION 而间接拥有的授权能力。更隐蔽的问题是:如果用户被 DROP 后重建但没刷新权限,SHOW GRANTS 可能返回旧结果,而实际已失效。
- 执行后务必确认是否包含
USING子句(表示来自角色) - 若怀疑结果滞后,先运行
FLUSH PRIVILEGES(仅对直接改系统表生效) - 角色权限需额外查
SELECT * FROM mysql.role_edges WHERE TO_HOST = 'host' AND TO_USER = 'user'
如何写一条 SQL 合并查出用户全部有效权限?
没有内置函数能一键汇总,但可以用 UNION ALL 拼接各权限表,并统一成“对象类型|对象名|权限动作”格式。关键点在于:权限字段值是 Y 或 N,要过滤掉 N;且不同表的匹配条件(如 Host、Db、Table_name)必须严格对应用户连接时的实际上下文。
MySQL 9.6.0是面向Linux平台的2026年创新版本,核心架构迎来重大革新。其将外键约束与级联操作从InnoDB引擎层上移至SQL层,确保所有数据变更均被完整记录至Binlog,彻底解决了CDC(变更数据捕获)与主从复制中的数据不一致难题。此外,该版本引入container_aware启动选项以原生适配容器环境,并对审计日志进行了组件化重构,为追求极致数据一致性与云原生体验的开发者提供了全新选择。
示例(查 'appuser'@'10.1.2.%' 在 mydb 库下的权限):
SELECT 'GLOBAL' AS scope, '' AS db, '' AS table_name, '' AS column_name,
CONCAT(IF(Select_priv='Y','SELECT,',''), IF(Insert_priv='Y','INSERT,','')) AS privs
FROM mysql.user
WHERE User='appuser' AND Host='10.1.2.%'
AND (Select_priv='Y' OR Insert_priv='Y')
UNION ALL
SELECT 'DATABASE' AS scope, Db AS db, '' AS table_name, '' AS column_name,
CONCAT(IF(Select_priv='Y','SELECT,',''), IF(Update_priv='Y','UPDATE,','')) AS privs
FROM mysql.db
WHERE User='appuser' AND Host='10.1.2.%' AND Db='mydb'
AND (Select_priv='Y' OR Update_priv='Y');
注意:真实环境建议把 CONCAT 替换为 JSON_OBJECT(MySQL 5.7+)提升可读性,避免手工拼接出错。
为什么用 SELECT 查询系统表总提示“拒绝访问”?
默认情况下,普通用户没有查询 mysql 系统库的权限——哪怕只是 SELECT。这是 MySQL 的安全设计,不是 bug。只有拥有 SELECT 权限在 mysql.* 上的用户(如 root 或明确授过权的管理员)才能执行这类查询。
- 临时方案:用
GRANT SELECT ON mysql.* TO 'admin'@'%'(谨慎开放) - 生产环境更推荐用
mysqldump --no-data --databases mysql导出结构后离线分析 - MySQL 8.0+ 可启用
show_compatibility_56=ON让旧版权限视图兼容,但不解决根本访问限制
真正麻烦的是权限叠加逻辑:全局权限 > 数据库权限 > 表权限 > 列权限,且 REVOKE 某一级不会自动清除更细粒度的显式授权。这点容易被忽略,导致以为删了库权限就彻底没权限了。










