必须显式撤销DROP权限才能确保不能删表,因MySQL权限叠加机制会使高层级(如库级)DROP覆盖低层级限制,旧账号可能残留全局或库级DROP权限,仅不授予DROP不等于安全。

不能直接用 DROP 权限控制“删表”,必须显式撤销或不授予它;只给 CREATE 和 ALTER 权限,同时确保没给 DROP,才能实现“能建表、改结构,但不能删表”。
为什么 GRANT CREATE, ALTER ON db.* 不等于“不能删表”?
很多人误以为只要不写 DROP 就安全了,但实际中容易踩两个坑:
一是旧账号可能已继承过全局或数据库级 DROP 权限(比如之前执行过 GRANT ALL);二是 MySQL 的权限叠加机制会让低层级权限覆盖高层级限制——哪怕你在表级 REVOKE DROP,若用户仍有数据库级 DROP,照样能删表。
所以关键不是“没给”,而是“确认没留”。
正确做法:先清权限,再精准授予权限
避免依赖“没授就等于没有”,直接用最小集原则操作:
CREATE USER 'dev_user'@'localhost' IDENTIFIED BY 'strong_pwd';GRANT CREATE, ALTER ON myapp_db.* TO 'dev_user'@'localhost';-
REVOKE DROP ON myapp_db.* FROM 'dev_user'@'localhost';(显式撤销,防残留) -
FLUSH PRIVILEGES;(必须执行,否则权限不生效)
注意:ALTER 允许改字段、加索引、重命名表等,但不包含 DROP TABLE;CREATE 包含建表、建视图、建存储过程等,也不含删表。
验证是否真不能删表
用该用户登录后执行:DROP TABLE test_table;,预期返回错误:ERROR 1142 (42000): DROP command denied to user 'dev_user'@'localhost' for table 'test_table'。
但要注意:TRUNCATE TABLE 是 DDL 操作,依赖 DROP 权限(MySQL 8.0+),所以也会被拦住;而 DELETE FROM test_table 属于 DML,只要没给 DELETE 权限,同样会拒绝——这点常被忽略。
表级细粒度控制(可选但推荐)
如果只想让某用户能改 users 表结构,但对 logs 表完全无权,就得用表级授权:
GRANT ALTER ON myapp_db.users TO 'dev_user'@'localhost';-
GRANT CREATE ON myapp_db.* TO 'dev_user'@'localhost';(建新表仍需库级CREATE) REVOKE DROP ON myapp_db.logs FROM 'dev_user'@'localhost';
表级 REVOKE 只影响对应表,不影响其他表权限,适合多角色混用场景。但注意:MySQL 不支持在表级授予 CREATE(建表只能在库级),所以建新表权限必须单独给库级 CREATE。
真正卡住删表动作的,从来不是“没给什么”,而是“明确撤掉什么”——尤其当账号经历过多次 GRANT 之后,残留权限比想象中更顽固。


















