SELECT、INSERT、UPDATE、DELETE 分别控制查询、插入、更新和删除数据的操作权限,均需显式指定数据库和表名(或通配符)才生效;其中SELECT含SELECT...INTO OUTFILE(受secure_file_priv限制),INSERT不含REPLACE(需DELETE权限),UPDATE可细化到列,DELETE不包含TRUNCATE(需DROP权限)。

SELECT、INSERT、UPDATE、DELETE 这四个权限到底控制什么
它们分别对应 SQL 的基础数据操作动词,不是“能连上数据库”或“能看到表名”,而是精确到「对哪些对象执行哪类语句」的开关。MySQL 用 GRANT 分配时,必须明确指定数据库名和表名(或通配符),否则权限不生效。
-
SELECT:允许执行SELECT查询,包括SELECT ... INTO OUTFILE(但导出路径受secure_file_priv限制) -
INSERT:允许INSERT、LOAD DATA INFILE(同样受secure_file_priv约束),但不包含REPLACE(需额外DELETE权限) -
UPDATE:只允许修改已有行,不影响新增或删除;字段级权限可细化到具体列,如GRANT UPDATE(col_a) ON db.t1 -
DELETE:仅控制DELETE FROM,不包含TRUNCATE TABLE(后者需要DROP权限)
ALTER、DROP、CREATE 这类 DDL 权限容易被误用
它们不涉及数据内容,而是影响表结构与对象存在性,权限粒度比 DML 更粗,且常被当成“开发账号标配”乱开,带来高风险。
-
ALTER允许ALTER TABLE、RENAME TABLE、ANALYZE TABLE,但不能改库名(需ALTER ROUTINE配合) -
DROP对数据库级生效时会删整个库,对表级生效时可删表——哪怕只有这一个权限,也能清空业务表 -
CREATE在数据库级表示能建新表,在表级无意义;若授予CREATE+INSERT,应用可能意外建临时表并写入敏感数据 - 注意:
INDEX权限独立存在,CREATE不自动包含它;加索引需显式授权
USAGE 权限不是“最低权限”,而是“零权限”
新建用户不授任何权限时,默认拥有 USAGE,它只表示「账号存在且可通过认证」,连 SHOW DATABASES 都看不到(除非开启 skip-show-databases 或有全局 SELECT)。
GRANT USAGE ON *.* TO 'app_user'@'10.0.1.%';
这种写法等价于创建账号但不给任何操作权。线上常见错误是以为 USAGE 能配合 WITH GRANT OPTION 做权限代理——不行,GRANT OPTION 必须搭配至少一个实际权限(如 SELECT)才有效。
如何验证某用户实际拥有的权限
别依赖记忆或文档,直接查 mysql.tables_priv 和 mysql.db 表,或用内置命令。注意:结果反映的是当前生效权限,不含未 FLUSH PRIVILEGES 的变更。
SHOW GRANTS FOR 'app_user'@'10.0.1.%';
如果返回空或只有 USAGE,说明没生效;若看到类似 GRANT SELECT, INSERT ON `myapp`.* TO ...,确认库名、主机段是否匹配当前连接来源。特别留意通配符:`myapp`.* 不等于 `myapp\_%`.*,前者只覆盖字面名为 myapp 的库。
字段级权限不会出现在 SHOW GRANTS 中,得查 mysql.columns_priv 表,生产环境极少需要,一开就难审计。










