MySQL权限是叠加生效的,用户只要在任意层级(全局/数据库/表)拥有DROP权限即可执行对应删除操作;关闭数据库级DROP权限后仍能删表,是因为其全局DROP权限未同步清除。

不能只关数据库级 DROP,必须同步清除全局 DROP 权限,否则用户仍能删任意库的表。
为什么关了「数据库权限」里的 DROP 还是能删表?
常见错误现象:Access denied 没报,但用户执行 DROP TABLE users 成功了——说明他根本没走你配置的那个数据库权限路径,而是靠全局权限删的。
MySQL 的权限是叠加生效的:只要用户在任意层级(全局 / 数据库 / 表)拥有 DROP,就能执行对应范围的 DROP 语句。而 phpMyAdmin 界面里「数据库特定权限」区域的 DROP 只控制对该库内对象的删除;如果用户在「Global privileges」里还勾着 DROP,他就等于有删整个实例所有库的权力。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 进入「用户账户」→「编辑权限」→ 先滚动到最上方「Global privileges」区域,把
DROP勾选彻底取消 - 再滚动到下方「Database-specific privileges」,选中目标业务库(如
app_prod),确认其「结构」组里的DROP也未勾选 - 特别注意:如果用户主机名是
'app_user'@'localhost',和'app_user'@'10.20.30.%'是两个独立账号,得分别检查
DELETE 权限和 DROP 权限根本不是一回事
误删整张表 ≠ 误删表里的数据。前者靠 DROP,后者靠 DELETE 或 TRUNCATE —— 而 TRUNCATE TABLE 实际上被 MySQL 当作 DROP + CREATE 处理,所以它依赖的是 DROP 权限,不是 DELETE。
也就是说:即使你只留 SELECT、INSERT、UPDATE,但没关 DROP,用户依然能用 TRUNCATE TABLE logs 清空日志表,且不触发 DELETE 权限检查。
使用场景举例:后台运营需要清理某天订单,但绝不能碰表结构。
- 只开
SELECT、INSERT、UPDATE、DELETE,关闭CREATE、ALTER、INDEX、DROP - 不给
GRANT OPTION,避免权限扩散 - 如果连行删除都不该有(比如报表只读账号),就只留
SELECT
改完权限后连接失败?大概率是没处理“默认库”问题
phpMyAdmin 没有「强制绑定默认数据库」的功能。如果你只在「Database-specific privileges」里给了 app_prod 权限,却没清掉全局权限,MySQL 在初始化连接时可能因权限冲突拒绝认证;更常见的是应用连接字符串没带 dbname=app_prod,首次执行 SELECT * FROM users 就报 Unknown database 'users'(其实是找不到默认库上下文)。
正确做法:
- 先在「Global privileges」里取消所有勾选(包括看似空的「Select all」)
- 再在「Database-specific privileges」点「Add privileges on the following database」,明确选中
app_prod - 确保应用代码里显式执行了
USE app_prod,或连接 DSN 中包含dbname=app_prod - 改完立刻用同账号在「SQL」标签页手动连一次,运行
SHOW DATABASES;看是否只列出app_prod
真正危险的从来不是「删错数据」,而是「删错对象层级」——DROP DATABASE 和 DROP TABLE 都只需要一个权限开关,且界面里藏得深、名字长得像、解释又模糊。每次点「执行」前,务必确认两处 DROP 都已关闭。



















