AFTER INSERT触发器虽单行插入时立即执行,但批量插入、事务内多操作及高并发下易引发竞态、锁等待和不可见性问题;定时任务虽有可控延迟,却具备批量处理、容错性强、不阻塞业务写入等优势,且多数报表场景无需毫秒级实时。

AFTER INSERT 触发器一写入就执行,不等调度周期,这是它“看起来更实时”的全部原因。但这个“实时”代价很高,且多数业务根本不需要毫秒级汇总。
触发器的“实时”只在单行插入时成立
只要 INSERT 语句提交,AFTER INSERT 触发器立刻运行,更新汇总表。没有延迟、不依赖外部调度——这点没错。
但以下情况它立刻失效:
- 批量插入(如
INSERT INTO orders SELECT ... FROM staging):触发器对每行都触发一次,可能重复更新同一汇总行,导致竞态或锁等待 - 事务中多条
INSERT操作:汇总值在事务结束前不可见,下游查询仍读到旧数据 - 并发写入同一个月/小时:即使用了
ON DUPLICATE KEY UPDATE,高并发下仍可能因锁排队拉长响应时间
定时任务的“延迟”其实是可控的精度权衡
用 EVENT(MySQL)或 SQL Server Agent 每 5 分钟跑一次存储过程,确实有最多 5 分钟延迟。但好处是:
- 一次处理所有新增数据,避免逐行开销和锁竞争
- 可加重试、日志、失败告警,出错不影响主业务
- 能安全做
MERGE或INSERT ... ON DUPLICATE KEY UPDATE,逻辑清晰可测 - 历史补数、跨时段修正、索引重建等操作天然支持
真正卡住实时性的,从来不是调度间隔,而是锁和事务上下文
你在 AFTER INSERT 里去 UPDATE summary_hourly,这个 UPDATE 和原始 INSERT 共享同一事务、同一行锁。一旦汇总表有唯一索引+外键+自身触发器,很容易触发 LCK_M_U 等待,把 10ms 插入拖成 800ms。
而定时任务在独立事务中运行,锁范围可控,还能设 WITH (NOLOCK) 或快照隔离读源表,完全不干扰业务写入。
更关键的是:95% 的报表类汇总,用户根本分不出“当前分钟”和“5 分钟前”的区别;但所有人都会投诉“下单变慢了”。那个“实时”,其实只是把问题从查询侧,悄悄搬到了写入侧。

















