触发器通过before/after事件捕获insert/update/delete变更,可访问old/new快照,但不可调外部api;仅限轻量本地操作,跨库行为差异大,且不感知非sql层变更。

触发器怎么捕获 INSERT/UPDATE/DELETE 变更
SQL 触发器本质是事件驱动的自动执行逻辑,不是轮询也不是日志解析。它在语句执行完成、事务提交前介入,能可靠拿到新旧数据快照。
关键点在于:必须用 BEFORE 或 AFTER 明确时机,且不同数据库对 OLD 和 NEW 的支持有差异:
-
BEFORE INSERT只能访问NEW(还没插入) -
AFTER UPDATE同时可用OLD(变更前)和NEW(变更后),适合做字段级比对 - PostgreSQL 支持
FOR EACH ROW级别,MySQL 5.7+ 才稳定支持行级触发器;SQL Server 用INSERTED/DELETED伪表替代
示例(PostgreSQL):
CREATE OR REPLACE FUNCTION log_user_change() RETURNS TRIGGER AS $$ BEGIN INSERT INTO user_change_log (op, user_id, old_email, new_email, changed_at) VALUES (TG_OP, NEW.id, OLD.email, NEW.email, NOW()); RETURN NEW; END; $$ LANGUAGE plpgsql;
为什么不能直接在触发器里调外部 API 或写 Kafka
触发器运行在数据库事务上下文中,所有操作必须满足 ACID。一旦触发器内发起网络请求失败,整个事务会回滚——这会导致业务主流程不可用,集成链路反而成了单点故障。
真实生产中,只允许触发器做轻量、本地、确定性操作:
- 写入同一库的审计表(如
user_change_log) - 更新物化视图或统计缓存字段(如
order_count) - 抛出自定义错误中断事务(如
RAISE EXCEPTION 'Invalid status transition')
想对接外部系统?得靠后续解耦步骤:比如用定时任务扫描 user_change_log 表,或用 Debezium 捕获 WAL 日志——触发器只是第一跳,不是终点。
一款AI图像与设计工具,主要用于将文本渲染为图片并返回临时本地文件路径,支持可选的 data URI。适用于 Clawhub 或 Codex,用于将纯文本或带样式的文本进行转换,适合需要提升相关任务效率的用户。
MySQL vs PostgreSQL 触发器行为差异坑点
看起来语法相似,但实际执行逻辑差很多,尤其涉及 NULL 和多行操作时:
- MySQL 的
BEFORE UPDATE中修改NEW.column会影响最终写入值;PostgreSQL 要显式RETURN NEW才生效 - MySQL 对批量
UPDATE(如UPDATE users SET status=1 WHERE id IN (1,2,3))只触发一次触发器,且OLD/NEW是单行伪记录 —— 无法逐行处理 - PostgreSQL 在
UPDATE多行时,触发器对每行各执行一次,OLD/NEW均为当前行快照 - SQL Server 的
INSTEAD OF触发器可拦截操作,但AFTER触发器看到的是已提交结果,不支持修改INSERTED表内容
所以跨数据库迁移触发器逻辑前,务必验证批量操作场景下的行为一致性。
触发器作为“变更监测器”的真实边界在哪
它只管 DML 层变更,不管数据来源。哪怕你是用 LOAD DATA INFILE、COPY、或者 ORM 的 bulk_create 插入,只要走 SQL 引擎,触发器就生效;但它对物理复制、备份恢复、直接文件覆盖等绕过 SQL 层的操作完全无感。
更隐蔽的问题是:触发器不捕获元数据变更(如 ALTER TABLE)、权限变更(GRANT)、或函数/视图定义更新。这些需要单独监听系统表或使用数据库原生变更流(如 PostgreSQL 的 logical decoding)。
真正上线前,必须确认三点:trigger_enabled 是否被误关、目标表是否被分区导致部分子表没挂触发器、以及有没有其他同名触发器因 FOLLOWS/PRECEDES 顺序错乱而覆盖逻辑。










