表级权限可精确控制到单张表的操作权限,如仅允许查orders和customers表;它比数据库级细、比列级实用,但不继承数据库权限,撤销需显式授权且必须FLUSH PRIVILEGES。

表级权限到底能控制到什么粒度?
MySQL 的表级权限(mysql.tables_priv)允许你精确到「某张或某几张家表」授予操作权限,比如只让开发人员能查 orders 和 customers 表,但不能碰 users 或 config。它比数据库级(mysql.db)更细,又比列级(mysql.columns_priv)更实用——多数业务场景下,表就是最小安全单元。
注意:表级权限不会自动继承数据库权限。即使你给了 app_db.* 的 SELECT 权限,再单独 revoke app_db.log_table 的 SELECT,也**不会生效**——因为 revoke 只能撤销你明确 GRANT 过的权限,而没显式授权过的表默认无权访问。
怎么用 GRANT 给指定几张表授权?
语法很简单,关键是把表名列清楚,用逗号分隔,每张表单独写一条 GRANT 更稳妥(避免通配符误伤):
GRANT SELECT, INSERT ON `myapp`.`orders` TO 'dev_user'@'%'; GRANT SELECT ON `myapp`.`customers` TO 'dev_user'@'%'; GRANT UPDATE ON `myapp`.`order_status` TO 'dev_user'@'%';
常见误区:
-
GRANT SELECT ON myapp.{orders,customers}❌ 不合法,MySQL 不支持花括号批量表名 -
GRANT SELECT ON myapp.orders, myapp.customers TO ...❌ 语法错误,每张表必须独立写一条 GRANT - 忘记执行
FLUSH PRIVILEGES;—— 权限变更后不刷新,新权限可能只在内存中,连接复用时仍按旧权限判断
为什么 SHOW GRANTS 看不到表级授权?
执行 SHOW GRANTS FOR 'dev_user'@'%' 时,你大概率只看到类似这样的结果:
GRANT USAGE ON *.* TO 'dev_user'@'%' GRANT SELECT, INSERT ON `myapp`.`orders` TO 'dev_user'@'%'
但 customers 和 order_status 的授权却没显示出来?这不是 bug,而是 MySQL 的显示逻辑:只有当用户拥有「该数据库下任意一张表的显式权限」时,才会把整个数据库(如 myapp.*)作为上下文展示;否则,只会逐条列出你真正 GRANT 过的表权限。
验证是否生效最直接的方式是切到该用户连接后实测:
-- 用 dev_user 登录后执行 SELECT * FROM myapp.customers; -- 应成功 SELECT * FROM myapp.users; -- 应报错 ERROR 1142 (42000): SELECT command denied
撤销某张表权限时,别漏掉 FLUSH
回收权限用 REVOKE,但和 GRANT 一样,它只更新内存中的权限缓存:
REVOKE INSERT ON `myapp`.`orders` FROM 'dev_user'@'%'; FLUSH PRIVILEGES;
容易踩的坑:
- 误用
DROP USER或直接删mysql.tables_priv表记录 —— 手动改系统表风险极高,且不触发权限重载机制 - 撤销后立刻测试失败,以为没生效,其实是客户端还连着旧连接;建议用新终端重新登录验证
- 如果用户同时有数据库级权限(比如
GRANT SELECT ON myapp.* TO ...),那么单靠REVOKE SELECT ON myapp.orders是无效的——必须先 revoke 数据库级权限,再单独 grant 其他表
表级授权不是银弹:它没法阻止用户通过 JOIN、子查询或视图间接访问未授权表,敏感字段仍需列级权限或应用层过滤。真正落地时,优先考虑最小权限原则+定期审计 mysql.tables_priv 表内容。










