mysql表级select权限需用grant select on database.table to 'user'@'host',database不可用,table可带反引号;撤销须精确匹配授权对象,不支持排除式语法;information_schema等系统库禁止显式授权;列级权限易因select 或orm导致报错。

如何给 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'。
功能说明(部分): 1,后台控制;所有前台显示页面,都在后台加以控制,不需登陆FTP即可更改全部的页面显示信息。 2,可选择用户发表的信息是否要求验证,如果选择只有通过验证后的信息才能在网页上显示。 3,推荐好友支持;当浏览信息时,可以选择“推荐”好友,只要输入对方的E-mail地址即可将此条信息发送到对的邮箱中。 4,预订信息支持;当访问者看到感兴趣的信息后,可选择“我要预订”向对方发送
这不是权限没给够,而是设计限制:该库只读且元数据访问由全局 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 很可能包含未预设授权的列或临时表,上线前务必用目标用户账号连上去跑一遍完整业务流。









