业务账号不能有ALTER、DROP、CREATE权限,因这些DDL操作会不可逆地破坏表结构且无法回滚,主从复制会放大错误;需显式回收残留权限并FLUSH PRIVILEGES,MySQL 8.0+推荐用角色隔离管理。

业务账号为什么不能有 ALTER、DROP、CREATE 权限
因为这些是 DDL 操作,直接改表结构,一旦误执行(比如 DROP TABLE users 或 ALTER TABLE orders DROP COLUMN amount),数据结构就不可逆地丢了。InnoDB 下 DDL 无法回滚,且主从复制会立刻放大错误。业务代码正常运行时根本不需要建表、删表、改字段——这些该由 DBA 在发布窗口里走审批流程操作。
显式收回 DROP 权限比“不授予”更关键
很多人只做 GRANT SELECT, INSERT, UPDATE, DELETE ON mydb.* TO 'app_user'@'%',以为没写 DROP 就安全了。但错在两点:
- 旧账号可能残留过
GRANT ALL ON mydb.*,导致库级DROP权限还在 - MySQL 权限叠加机制:哪怕你在表级
REVOKE DROP ON mydb.t1,只要用户仍有DROP ON mydb.*,照样能删t1
所以必须主动清理:
REVOKE DROP ON mydb.* FROM 'app_user'@'%';<br>REVOKE CREATE ON mydb.* FROM 'app_user'@'%';<br>REVOKE ALTER ON mydb.* FROM 'app_user'@'%';<br>FLUSH PRIVILEGES;
注意:FLUSH PRIVILEGES 不可省,否则权限变更不生效。
用 MySQL 8.0 角色隔离 DDL 权限更可靠
如果你的 MySQL 是 8.0+,别再给每个账号单独授/撤权。用角色把 DDL 权限抽出来集中管理:
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
CREATE ROLE 'ddl_admin';<br>GRANT ALTER, DROP, CREATE ON *.* TO 'ddl_admin';<br>GRANT 'ddl_admin' TO 'dba_user'@'10.20.%';<br>SET DEFAULT ROLE NONE TO 'dba_user'@'10.20.%';
这样 dba_user 默认没有 DDL 权限,只有显式执行 SET ROLE 'ddl_admin' 后才临时拥有——而且这个语句本身还能被审计日志捕获。业务账号则完全不绑定任何含 DDL 的角色。
验证账号是否真不能执行 DDL
别信配置,要实测。用业务账号登录后,挨个试几条典型 DDL:
-
DROP TABLE test;→ 应报ERROR 1142 (42000): DROP command denied -
TRUNCATE TABLE test;→ MySQL 8.0+ 也依赖DROP权限,同样应被拒 -
ALTER TABLE test ADD COLUMN x INT;→ 应报ERROR 1142 (42000): ALTER command denied
特别注意:TRUNCATE 是 DDL,不是 DML,它不走事务、不触发触发器、不记录 binlog(除非 binlog_format=ROW),且恢复极难——所以必须和 DROP 一起卡死。
真正卡住 DDL 的从来不是“没给”,而是“确认没留”。尤其当账号经历过多次 GRANT 和迁移后,残留权限比文档写得更隐蔽。每次上线新服务前,用 SHOW GRANTS FOR 'app_user'@'%' 检查一遍,比事后救火便宜得多。










