MySQL不支持AFTER ALTER触发器,需通过解析binlog或人工登记schema_change_log表来捕获DDL变更,同时注意权限、存储周期与索引优化。

用 AFTER ALTER 触发器做不到,MySQL 没这东西
MySQL 不支持 AFTER ALTER TABLE 这类 DDL 触发器,所有想靠触发器自动捕获 ALTER TABLE 操作的方案,在原生 MySQL 里直接失效。这不是配置问题,是内核层面不提供。你看到的“触发器监听 DDL”基本都混用了代理层(如 ProxySQL)、binlog 解析、或外部审计工具。
真正可行的方案:解析 mysql-bin.0000xx 日志
DDL 变更会写入 binlog(只要 log_bin=ON 且 binlog_format=STATEMENT 或 MIXED),所以最稳定的方式是解析 binlog 获取 ALTER、CREATE、DROP 语句。实际操作中注意:
-
mysqlbinlog命令能直接输出可读 SQL,但需确保用户有REPLICATION CLIENT权限 -
binlog_format=ROW时 DDL 仍以 statement 形式记录,不影响解析,但 DML 不会显示字段级变更,别误以为漏了 - 生产环境建议用轻量解析库(如 Python 的
mysql-replication),避免手动轮询和解析偏移风险 - 别把 binlog 解析服务和主库部署在同一台机器上,磁盘 I/O 和 CPU 竞争容易拖慢主库
建一张 schema_change_log 表存人工/半自动记录
在缺乏统一 DDL 网关的中小团队,最务实的做法是:把变更流程卡在执行前,强制填表。这张表不是用来“自动捕获”,而是作为操作凭证和回溯依据:
- 字段至少包含:
id、table_name、operation(ADD COLUMN/MODIFY COLUMN等)、sql_text、executed_by、executed_at - 禁止直接对线上表执行
ALTER,必须先 INSERT 这张表,再由运维脚本或审批系统校验后执行(可用init_connect拦截非白名单用户,但无法拦 root) - 注意
sql_text字段要用TEXT类型,有些ALTER语句超长(比如加多个字段+注释+索引),VARCHAR(255)肯定存不下
别忽略权限与保留周期这两个硬约束
日志不是记下来就完事。binlog 默认只保留几天(看 expire_logs_days),schema_change_log 表没分区或归档机制,半年后查一条 2023 年的字段变更可能要扫几千万行。
- binlog 解析结果建议落地为冷表(如
schema_change_history),按月分区,定期用mysqldump --where导出归档 - 给
schema_change_log加上INDEX(executed_at, table_name),否则按时间范围查变更会全表扫 - DBA 账号执行 DDL 时,
current_user()和user()可能不同——前者是权限上下文,后者带 host,记录时用user()才能准确定位到人
DDL 日志的本质不是技术炫技,是让“谁在什么时候改了什么”这件事不可抵赖。自动解析有延迟和覆盖盲区,人工登记又怕流于形式,中间那个平衡点往往藏在流程卡点设计里,而不是代码里。










