MySQL撤销权限报错1147:用户无指定表权限问题排查
问题根源与解决方案
核心原因
MySQL的权限系统采用层级化设计,权限分为全局级(*.*)、数据库级(db.*)、表级(db.table)等多个层级,且遵循以下关键规则:
- 高权限层级会自动覆盖低层级权限(比如全局
SELECT权限会让用户拥有所有数据库/表的查询权限) REVOKE操作仅能撤销显式授予的同层级权限,无法撤销通过高权限层级继承而来的低层级权限
你给JOHN@localhost授予的是全局SELECT权限(GRANT SELECT ON *.* TO JOHN@localhost),此时MySQL仅在全局权限表中添加一条记录,不会为每个数据库/表生成单独的权限条目。当你尝试撤销sakila.actor表的权限时,由于该用户从未被显式授予过这个表级的SELECT权限,MySQL找不到对应的权限记录,因此抛出报错:
Error Code: 1147. There is no such grant defined for user 'JOHN' on host 'localhost' on table 'actor'
单独授予sakila.*权限后依然报错的原因同理:此时用户同时拥有全局和数据库级权限,但sakila.actor的访问权限还是来自这两个层级的继承,没有单独的表级权限条目,所以REVOKE仍无法找到对应记录。只有当你显式执行GRANT SELECT ON sakila.actor TO JOHN@localhost后,MySQL才会在表级权限表中生成这条记录,此时REVOKE才能生效。
正确处理方式
如果需要限制用户访问特定表,不能基于全局权限直接撤销,必须先收回高权限层级,再显式授予用户需要的权限:
- 先收回全局
SELECT权限
REVOKE SELECT ON *.* FROM JOHN@localhost;
- 显式授予用户允许访问的所有数据库/表权限,排除需要限制的表
比如,允许用户访问除sakila.actor外的所有表:
-- 授予所有数据库的查询权限 GRANT SELECT ON *.* TO JOHN@localhost; -- 收回sakila库的权限,生成数据库级权限条目 REVOKE SELECT ON sakila.* FROM JOHN@localhost; -- 重新授予sakila库权限,再撤销指定表的权限 GRANT SELECT ON sakila.* TO JOHN@localhost; REVOKE SELECT ON sakila.actor FROM JOHN@localhost;
内容的提问来源于stack exchange,提问作者Hasan
相关产品推荐
相关产品推荐

