MySQL列级权限仅支持SELECT/INSERT/UPDATE/REFERENCES,不支持DELETE等行级操作;列权限必须依附表级权限,元数据存于mysql.columns_priv,生产环境推荐用视图替代。

列级权限只支持 SELECT/INSERT/UPDATE/REFERENCES,DELETE 不行
MySQL 确实允许对字段做细粒度控制,但仅限 SELECT、INSERT、UPDATE、REFERENCES 四类操作;DELETE、ALTER、DROP 等天然作用于整行或整表,语法上就不支持括号列名。你若执行:GRANT DELETE (salary) ON hr.employees TO 'analyst'@'%';,会直接报错 ERROR 1064 (42000)。
常见误判是看到 SHOW GRANTS 显示了列名,就以为所有操作都受控——其实只是 SELECT/INSERT/UPDATE 的列白名单生效了,其他语句压根不走这套逻辑。
-
SELECT (name, dept):用户查SELECT *时,未授权列(如salary)值返回NULL,但字段名仍暴露 -
INSERT (name, email):必须显式写列名,INSERT INTO t VALUES (...)全字段插入会被拒绝 -
UPDATE (status):SET status = 'done', updated_at = NOW()中只要出现未授权列,整条语句失败
GRANT 必须显式列出字段,不能混用全表和列级授权
语法上,列名必须紧贴表名后用括号包裹,且同一 GRANT 语句中不能混写“带列名”和“不带列名”的权限。下面这句非法:GRANT SELECT (id), INSERT ON mydb.users TO 'u'@'%';
真正有效的写法是分开授权:GRANT SELECT (id, name) ON mydb.users TO 'u'@'%';GRANT INSERT (name, email) ON mydb.users TO 'u'@'%';
注意两点:
- 如果后续又执行了
GRANT SELECT ON mydb.users TO 'u'@'%';,之前所有列级SELECT权限即失效——高权限覆盖低权限 -
WHERE、ORDER BY、GROUP BY中引用的列也需在SELECT列权限范围内,否则报ERROR 1142(例如SELECT name FROM t WHERE salary > 5000会因salary无SELECT权限而失败)
列权限依赖表级权限存在,且元数据分散在 mysql.columns_priv
列级权限不是独立生效的,它必须叠加在对应表级权限之上。比如用户没有 SELECT 表权限,只授了 SELECT (name),那这条列授权实际无效。
权限元数据不存于 mysql.user 或 mysql.db,而是在 mysql.columns_priv 表里。查具体配置得用:SELECT * FROM mysql.columns_priv WHERE User='u' AND Host='%' AND Db='mydb' AND Table_name='users';
这个表有几个关键点容易踩坑:
-
Column_priv字段是逗号分隔字符串(如Select,Update),不是布尔值 - 手动往该表
INSERT或UPDATE后,必须执行FLUSH PRIVILEGES;才生效 -
SHOW GRANTS FOR 'u'@'%'只显示部分信息,不能替代查系统表
生产环境慎用列级权限,优先走视图隔离路径
列级权限在审计、迁移、主从同步时极难维护:备份恢复可能漏掉 mysql.columns_priv,客户端工具(如 DBeaver)或 ORM(如 Django ORM)发 SELECT * 时,MySQL 返回可访问列 + NULL 占位,结构依然泄露,且日志里看不出是否越权读取。
更可靠的做法是建安全视图:CREATE VIEW users_public AS SELECT id, name, dept FROM users;
然后只授 SELECT 权限给视图,并确保用户对基表 users 完全无权限。
这样做有三个硬性好处:
- 字段白名单显式固化,基表加新敏感列不会自动透出
- 视图可叠加行级过滤(如
WHERE id = CURRENT_USER()),实现行列双控 - 权限边界清晰:用户只能查视图,基表权限为零,彻底杜绝绕过
真正麻烦的从来不是语法怎么写,而是权限变更后没人记得去同步 mysql.columns_priv,或者某次误授全表 SELECT 就让所有列级控制归零。视图方案把权限逻辑收口到 DDL 层,比靠人维护几十行 GRANT 语句靠谱得多。


















