幂等写入是什么
同一批数据重复写入多次,最终结果与只写一次完全一致,就称为幂等写入。它是数据管道里最实用的容错手段:任务失败后不必精确知道执行到哪一步,直接整段重跑即可,重复部分会被自然收敛掉。
三种常用手段
一是按业务主键 upsert,重复记录覆盖而不新增;二是分区覆盖写入,重跑时先按分区删再写,保证该分区的数据只有这一次作业的结果;三是写临时表后原子切换(或重命名为正式表),失败时正式表不受影响。三者共同的前提是存在稳定的主键或分区键。
基本信息
| 目标 | 同一批数据重跑多次,结果保持一致 |
|---|---|
| 常用手段 | 主键 upsert、分区覆盖、临时表切换 |
| 前提 | 有稳定的业务主键或分区键 |
| 配套 | 与至少一次投递组合,可逼近精确一次的效果 |
| 反面情况 | 追加写入、自增主键判重、跨天全表覆盖 |
典型使用场景
- 实时链路至少一次投递后,落库端用主键 upsert 收敛重复
- 离线日批重跑:按当天分区整体覆盖,不需要逐条判断是否需要更新
- 维表加工:写临时表校验通过后再重命名,避免下游读到中间态
- 补数场景:重刷受影响的历史分区,其他分区不受影响
- 多来源合并落地:不同来源写同一张表时按主键归并
MySQL 幂等写入
MySQL 幂等写入
-- 主键冲突时更新,重复写入结果一致
INSERT INTO dwd_order (order_id, amount, updated_at)
VALUES (%s, %s, %s)
ON DUPLICATE KEY UPDATE amount = VALUES(amount), updated_at = VALUES(updated_at);数仓分区覆盖
数仓分区覆盖
-- 只覆盖当天分区,重跑多少次结果都相同
INSERT OVERWRITE TABLE dwd_order PARTITION (dt = '2026-10-11')
SELECT order_id, amount, updated_at FROM ods_order WHERE dt = '2026-10-11';
-- 注意:不写 PARTITION 子句的 INSERT OVERWRITE 会清空整表重建三种手段对比
| 手段 | 适用 | 代价 |
|---|---|---|
| 主键 upsert | 实时流落库、单条粒度更新 | 需要唯一键与索引,写入有额外开销 |
| 分区覆盖 | 日批、按天分区的明细与汇总 | 只对整分区有效,无法只更新分区内一行 |
| 临时表切换 | 对外提供查询的表结构变更或整表重算 | 需要额外存储与一次原子重命名操作 |
不带分区子句的 INSERT OVERWRITE 会清空整张表重建,误用一次就是全量事故;写这条语句前必须确认分区表达式存在且取值正确。
幂等与事务解决的是不同问题:幂等保证「重跑不产生重复」,事务保证「多次读写要么全成功要么全失败」。跨库写目标环境时,先做到幂等,再考虑事务边界。