目标
坏数据一旦流进数仓和报表,修复就变成考古工程。在阶段边界设断言门禁,让问题停在它进来的那一站:隔离区带着证据(失败断言、肇事行样本、上游血缘),修复后的重放必须原样过完全部断言才能重新入列——通过是挣来的,不是假设的。
步骤要点
- 按阶段边界定义不变量:键非空、取值范围、唯一性、引用一致性、行数带宽,每处边界一套具名可版本化的断言。
- 门禁失败即关闭:断言失败立即拦截批次进隔离区,连同失败断言与肇事行样本,下游永远看不到。
- 隔离区带诊断上下文:存失败断言结果、输入血缘与行样本,分诊无需重跑管道。
- 按不变量类别路由:键或引用失败立即打页找管道负责人,范围或计数漂移进早间质量摘要。
- 修复后全程复检重放:隔离批次走同一组门禁,全部断言通过才允许并入下游。
排错提示
门禁只打日志不拦截等于没有门禁,把失败关闭与隔离落库做成硬行为;修完手工把隔离数据塞回去跳过了验证,重放必须过原来失败的那几条断言;断言越攒越慢就分级:键类全量跑、范围类抽样跑,门禁预算要写进断言设计。
适用边界
断言只能覆盖可陈述的不变量,语义级错误(合法但错误业务含义)需人工抽检补充;失败关闭在强时效管道上会推迟产出,需为隔离与重放预留排程窗口。
代码示例
gate: load_orders (stage boundary)
assertions:
order_id not-null, unique PASS
status in {pending,paid,...} PASS
total_cents > 0 AND < 10_000_000 FAIL (17 rows = 0)
customer_id 97% referential match FAIL (412 orphans)
result: BATCH QUARANTINED
reason: 2 failed assertions + row samples
lineage: extract.run 2026-10-22-00-31
routing: referential failure -> page pipeline owner
replay (after fix): all assertions PASS -> merge