MySQL触发器无法拦截DROP TABLE,因其仅支持DML操作;防御需权限隔离(REVOKE DROP)与审计兜底(通用日志+告警)。
MySQL 里用 BEFORE DELETE 触发器拦不住 DROP TABLE
触发器根本监听不到
,它只响应
、
、
这类 DML 操作。而删表是 DDL,MySQL 的触发器机制不支持拦截。很多同学配完
就以为万事大吉,结果一执行
,触发器连影子都没见着。
真正能起作用的路径只有两条:权限隔离 + 审计兜底。
用 REVOKE 剥夺普通账号的 DROP 权限
这是最直接有效的防线。只要账号没被显式授予
权限,哪怕有
权限,也执行不了删表命令。
确认生效:查
,输出里不能出现
开发/运维账号另建专用高权账号(比如
),严格管控登录终端和会话时长
注意:
会隐式包含
,千万别给业务账号开这个
DELETE 全表时靠 WHERE 1=0 拦截误操作
即便不能防删表,至少得防
这种漏写
的事故。触发器可以在这里卡一下。
示例触发器逻辑:
但要注意几个硬伤:
依赖
,在 MySQL 8.0+ 默认关闭 performance_schema 时可能查不到
字段
无法区分
和
—— 都是全表扫描,触发器没法看 SQL 文本细节
更靠谱的做法是:强制所有 DELETE 必须带非空
条件,并在应用层做语法校验(比如 ORM 层禁止无条件 delete)
真正的兜底:开启通用查询日志 + 自动告警
权限和触发器都只是前置限制,出事后的快速定位和止损,靠的是可追溯的日志。
开启
,日志输出到表(
),避免文件写满磁盘
用定时任务或监控脚本扫描
表,匹配关键词:
、
(结尾无 WHERE)、
匹配到即发企业微信/钉钉告警,并自动 kill 对应
注意:通用日志有性能开销,生产环境建议仅在核心库开启,且日志保留不超过 24 小时
权限控制是底线,日志审计是后视镜。没人能保证永远不手滑,但得让手滑之后三秒内有人知道、五秒内能拦住。
DROP TABLEINSERTUPDATEDELETEBEFORE DELETEDROP TABLE users;DROPDELETEREVOKE DROP ON mydb.* FROM 'app_user'@'%';SHOW GRANTS FOR 'app_user'@'%';DROPdba_adminGRANT ALL PRIVILEGESDROPDELETE FROM users;WHERECREATE TRIGGER prevent_full_delete
BEFORE DELETE ON users
FOR EACH ROW
BEGIN
IF (SELECT COUNT(*) FROM information_schema.PROCESSLIST
WHERE ID = CONNECTION_ID() AND INFO LIKE 'DELETE FROM users%') > 0
THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Full table delete blocked: missing WHERE clause';
END IF;
END;information_schema.PROCESSLISTINFODELETE FROM users WHERE id = 123;DELETE FROM users;WHEREgeneral_log = ONgeneral_log_table = ONmysql.general_logDROP TABLEDELETE FROM [a-z_]+;$TRUNCATE TABLECONNECTION_ID()