一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

如何在MySQL中撤销REVOKE某个用户的特定表删除权限

时间:2026-06-23 11:06:52 编辑:袖梨 来源:一聚教程网

MySQL不支持只撤某张表的DROP权限,必须显式写出数据库名和表名,且ON子句须与原始GRANT完全一致,否则静默失败或报ERROR 1141;唯一合法写法为REVOKE DROP ON db_name.tbl FROM 'user'@'host'。

不能只撤“某张表的 DROP 权限”——MySQL 不支持模糊撤销,必须显式写出数据库名和表名,且 ON 子句必须和当初 GRANT 时完全一致,否则静默失败或报 ERROR 1141

REVOKE DROP ON db_name.tbl 是唯一合法写法

MySQL 的权限系统不识别“从库级权限里抠出一张表”,它只认完全匹配的 ON 范围。哪怕你当初是用 GRANT DROP ON mydb.* 授的权,只要想精确到单表,就必须改用表级语法:

  • REVOKE DROP ON mydb.users FROM 'u'@'%' ✅ 正确(假设当初就是这么授的)
  • REVOKE DROP ON mydb.* FROM 'u'@'%' ❌ 错误(这是撤整个库,不是单表)
  • REVOKE DROP ON *.users FROM 'u'@'%' ❌ 语法错误
  • REVOKE DROP ON users FROM 'u'@'%' ❌ 缺少数据库名,报错

表名含特殊字符(如横线、点)必须用反引号: REVOKE DROP ON `my-db`.`user_log` FROM 'u'@'%'

常见错误现象:ERROR 1141 或看似成功实则无效

执行 REVOKE 后提示 Query OK,但用户还能删表?大概率是 ON 子句没对上。重点检查:

  • 大小写是否一致(lower_case_table_names = 0 时,MyDB.Usersmydb.users
  • 当初 GRANT 是不是带了反引号?那 REVOKE 也得带
  • 用户是不是有多个 host 记录?'u'@'localhost''u'@'%' 是两个独立账号,必须分别处理
  • 先查原始授权:SHOW GRANTS FOR 'u'@'%',逐行确认 ON 后的内容

单撤 DROP 权限防不住删表,必须组合回收

用户仍可能通过其他路径绕过:

  • ALTER TABLE t RENAME TO t_bak + CREATE TABLE t → 需同步 REVOKE ALTER, CREATE ON mydb.users FROM 'u'@'%'
  • 持有 SUPERSYSTEM_VARIABLES_ADMIN → 可关 sql_log_bin 直接 DDL,REVOKE DROP 对其完全无效
  • TRUNCATE TABLE 不依赖 DROP 权限(MySQL 8.0+ 需单独 TRUNCATE 权限,旧版靠 DELETE+DROP)→ 若目标是防数据丢失,还得 REVOKE TRUNCATE, DELETE ON mydb.users FROM 'u'@'%'

撤销后权限不立即在旧连接中生效

执行 REVOKE 成功只更新服务端权限表,已建立的连接(包括应用连接池里的长连接)仍用原权限快照。验证是否真生效的唯一方式是:

  • 立刻运行 SHOW GRANTS FOR 'u'@'%',确认输出里已无对应 DROP
  • 用新连接测试:mysql -u u -h db-host -p -e "DROP TABLE mydb.users"
  • 生产环境需通知应用滚动重启连接池,或等连接超时驱逐

真正难的不是写对那条 REVOKE,而是搞清权限在哪一层被授予过、有没有角色继承、当前连接是否还在用旧快照——这些不查系统表、不重连验证,根本没法闭环。

热门栏目