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表,生产环境极少需要,一开就难审计。
