能实现新增数据自动同步,但仅限单库单实例低频场景;跨库、高并发或批量插入时会失效甚至引发死锁或数据不一致。

触发器能实现新增数据自动同步,但仅限于单库、单实例、低频写入场景;跨库、高并发或批量插入时它会失效甚至引发死锁或数据不一致。
BEFORE INSERT 是唯一能安全预写同步记录的位置
在 MySQL 或 PostgreSQL 中,AFTER INSERT 触发器里执行 SELECT 查刚插入的行,可能查不到——因为事务尚未提交,READ COMMITTED 隔离级别下不可见。更糟的是,INSERT INTO t1 VALUES (), () 这类批量插入,触发器每次只看到一行,无法批量处理目标表。
- 改用
BEFORE INSERT:直接用NEW.id(或生成的 UUID)构造同步记录,不依赖主表查询 - 若主表无自增主键,需在触发器内调用
nextval()(PostgreSQL)或LAST_INSERT_ID()(MySQL)前手动赋值,否则NEW.id为空 - Supabase 的
auth.users表是只读的,不能直接建BEFORE INSERT触发器;必须在public.profiles上建AFTER INSERT,再通过user_id = NEW.id关联回写
INSERT ON DUPLICATE KEY UPDATE 比先查后插更可靠
多语言表或扩展信息表常用 (entity_id, lang_code) 作联合唯一键。此时硬编码 INSERT ... SELECT 容易因并发导致主键冲突,而 ON DUPLICATE KEY UPDATE 是原子操作,避免竞态。
- 确保目标表有
UNIQUE KEY (entity_id, lang_code),否则ON DUPLICATE KEY不生效 - 写法必须是
VALUES (NEW.id, 'zh', NEW.title) ON DUPLICATE KEY UPDATE value = VALUES(value),不是value = NEW.title——后者在重复时取的是旧值,不是本次插入值 - PostgreSQL 不支持
ON DUPLICATE KEY,得用INSERT ... ON CONFLICT DO UPDATE,且DO UPDATE SET value = EXCLUDED.value才对
批量插入默认跳过触发器,这是设计,不是 bug
LOAD DATA INFILE、ORM 的 bulk_create()、INSERT INTO ... VALUES (), () 全部绕过触发器。SQL Server 的 INSERT SELECT 同样不触发——哪怕只插一行。
- 想强制走触发器,只能拆成单行事务:循环 +
BEGIN TRANSACTION+ 每次单条INSERT - 生产环境更推荐应用层异步任务兜底:监听数据库日志(如 Debezium)、或用定时任务扫描主表
updated_at > last_sync_time的增量 - SQL Server 的
INSTEAD OF触发器可拦截批量插入,但必须手动解析INSERTED表并重写全部逻辑,复杂度陡增,易出错
真正容易被忽略的是:触发器函数返回值决定是否继续执行。PostgreSQL 要求返回 NEW 或 OLD,返回 NULL 会跳过后续操作;MySQL 在 BEFORE 触发器中给 NEW.xxx 赋值后,必须显式 SET NEW.xxx = ...,否则修改无效。这些细节一错,同步就静默失败。











