MySQL原生不支持DDL触发器,所有版本均无法创建AFTER ALTER TABLE等触发器;社区版唯一可行方案是启用server_audit插件并仅开启QUERY_DDL事件,配合日志实时监控与information_schema结构快照比对实现DDL审计。

MySQL原生不支持DDL触发器,别白费劲写AFTER ALTER TABLE
MySQL所有版本(包括8.0.34、9.6.0)都不支持针对CREATE TABLE、ALTER TABLE、DROP TABLE等DDL语句的触发器。你写的CREATE TRIGGER ... AFTER ALTER TABLE会直接报错ERROR 1415 (0A000): Not allowed to return a result set from a trigger——这不是语法写错了,是MySQL压根没这个能力。试图用DML触发器“间接推断”结构变更(比如监控某列突然允许NULL)也完全不可靠:字段注释修改、索引增删、MODIFY COLUMN重排序都不会产生任何DML日志。
社区版唯一可行方案:启用server_audit插件并限定QUERY_DDL
MySQL社区版想捕获未授权DDL,必须用server_audit插件,并且只开QUERY_DDL事件。其他选项全是坑:
-
general_log会混入海量业务SQL,grepALTER漏掉大小写或空格就丢事件,且不记录失败操作(如权限不足的ALTER根本不会进日志) -
audit_log插件在标准社区版里基本不存在,INSTALL PLUGIN audit_log SONAME 'audit_log.so'必报Plugin 'audit_log' is not loaded -
performance_schema需8.0.14+且要手动开statement/abstract/ddl仪器,但该仪器实际不捕获ALTER TABLE——它只对CREATE DATABASE等极少数DDL有效
正确操作三步:
- 确认插件路径:
SHOW VARIABLES LIKE 'plugin_dir';,检查目录下是否有server_audit.so - 加载并启用:
INSTALL PLUGIN server_audit SONAME 'server_audit.so';,然后SET GLOBAL server_audit_events = 'QUERY_DDL'; - 指定日志路径:
SET GLOBAL server_audit_file_path = '/var/log/mysql/ddl_audit.log';,确保/var/log/mysql目录存在且属主为mysql
告警不能只靠日志文件,得加一层实时解析和过滤
server_audit日志是纯文本,每行含user、host、query、status(0=成功),但不自动发告警。你需要一个轻量脚本轮询新内容:
- 用
tail -n 1 -f /var/log/mysql/ddl_audit.log持续监听,配合grep -E '(CREATE|ALTER|DROP) +TABLE'提取关键行 - 重点过滤
host字段:非DBA网段(如192.168.100.%)或通配符%来源的ALTER TABLE必须告警 - 区分
status != 0的失败DDL——这可能是试探性攻击,比如GRANT SUPER ON *.*被拒,但已暴露恶意意图 - 避免重复告警:用
md5sum对user@host + query做哈希,10分钟内相同哈希跳过
示例判断逻辑(shell):if [[ "$LINE" =~ "ALTER TABLE" ]] && [[ "$LINE" =~ "host:.*[^192\.168\.100]" ]]; then curl -X POST https://your-webhook/notify?msg="Unauth DDL from $USER@$HOST"; fi
别忽略information_schema快照比对这个兜底手段
插件可能被禁用或日志轮转丢失,所以必须搭配定期结构快照:
- 每天凌晨跑一次存储过程,把
SELECT CONCAT(table_schema, '.', table_name), MD5(GROUP_CONCAT(CONCAT(column_name, ':', data_type, ':', is_nullable, ':', column_default) ORDER BY ordinal_position)) FROM information_schema.COLUMNS GROUP BY table_schema, table_name存入审计表 - 对比时只关注
MD5值变化,不比字段顺序(避免ALTER TABLE ... MODIFY COLUMN重排导致误报) - 发现差异后,反查
server_audit日志中最近2小时的ALTER记录,确认操作人;若无记录,说明DDL绕过了审计插件(比如用root账号直连且插件未加载)
这个组合最危险的盲区是:DDL在事务中执行(如BEGIN; ALTER TABLE ...; COMMIT;),server_audit仍能捕获,但information_schema快照可能读到中间状态——所以快照务必在低峰期、显式加SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED执行。


















