mysql用户只能访问部分表_mysql权限控制方法

来源:这里教程网 时间:2026-02-28 20:50:39 作者:

如何给 MySQL 用户授予指定表的 SELECT 权限

直接用

GRANT SELECT ON database_name.table_name TO 'user'@'host'
即可,不需要先创建用户(如果用户已存在)。注意
database_name
不能是通配符
*
,必须写具体库名;
table_name
可以是具体表名,也可以用反引号包裹含特殊字符的表名。

常见错误是漏掉数据库名,比如只写

GRANT SELECT ON table_name TO ...
,MySQL 会报错
ERROR 1144 (42000): Illegal GRANT/REVOKE command
。权限粒度最小到表级,不支持“某个库下除某几张表外全部授权”这种排除式语法。

执行后必须跟
FLUSH PRIVILEGES
(仅当直接操作
mysql
系统表时才强制需要;用
GRANT
命令通常自动生效)
如果用户从任意主机连接,
'user'@'%'
中的
%
不匹配 localhost,需额外授权
'user'@'localhost'
权限是叠加的:用户已有库级 SELECT 权限,再授表级权限不会冲突,但撤销库级权限不影响已授的表级权限

撤销某张表的权限但保留其他表访问权

MySQL 不支持“撤销某张表而保留同库其他表”的原子操作,

REVOKE
必须明确指定和
GRANT
完全一致的对象范围。例如之前用
GRANT SELECT ON mydb.orders TO 'u1'@'%'
授了权限,那么撤销就得写
REVOKE SELECT ON mydb.orders FROM 'u1'@'%'

容易踩的坑是误用

REVOKE SELECT ON mydb.* FROM ...
——这会把整个库所有表的 SELECT 权限都撤掉,包括你本想保留的那些。

没有“批量排除某几张表”的语法,要保留 9 张表、只撤 1 张,就得先
REVOKE
全部,再对那 9 张重新
GRANT
SHOW GRANTS FOR 'u1'@'%'
是验证当前权限的唯一可靠方式,别依赖记忆或旧文档
权限变更在当前连接中立即生效,但已打开的事务不受影响

为什么对 INFORMATION_SCHEMA 表授权总是失败

MySQL 禁止对

INFORMATION_SCHEMA
显式授权,任何类似
GRANT SELECT ON INFORMATION_SCHEMA.TABLES TO ...
的语句都会报错
ERROR 1044 (42000): Access denied for user ... to database 'INFORMATION_SCHEMA'

这不是权限没给够,而是设计限制:该库只读且元数据访问由全局

SELECT
权限或更细粒度的
SHOW DATABASES
/
PROCESS
等特权间接控制。普通用户默认能查自己有权限的库下的表信息,但看不到其他库结构。

如果用户连
SHOW TABLES
都被拒绝,先确认是否至少有对应库的
USAGE
权限(新建用户默认有)
想让应用能自动发现表结构,与其绕过限制,不如在业务库中建视图或提供元数据表
performance_schema
sys
同样不可直接授权,逻辑一致

使用列级权限时要注意什么

MySQL 支持列级权限(如

GRANT SELECT(col1, col2) ON db.t1 TO 'u'@'%'
),但实际使用率极低,因为 ORM、连接池、查询构建器往往生成
SELECT *
或动态字段列表,一旦碰到未授权列就会报错
ERROR 1142 (42000): SELECT command denied to user ... for column 'col3'

列权限是独立于表权限的,即使用户已有整表

SELECT
,再单独授某几列权限也不会覆盖或冲突;但只要查询中涉及任一未授权列,整个语句就失败。

无法用列权限实现“隐藏敏感字段”,因为
SELECT *
仍会触发拒绝;必须确保所有 SQL 显式列出已授权列
备份工具(如
mysqldump
)默认用
SELECT *
,列权限会导致备份失败
权限检查发生在执行阶段,不是解析阶段,所以函数、子查询中引用未授权列同样报错

权限系统本身不复杂,难的是和真实业务查询模式对齐。比如一个 Web 应用用了 Doctrine ORM,默认生成的 SQL 很可能包含未预设授权的列或临时表,上线前务必用目标用户账号连上去跑一遍完整业务流。

相关推荐