上线当天明明成功了,为什么第二天才失败?
用 AccountBalanceSnapshot 日批任务对照 initialize / maintain 路径,再比较固定结果对象与 CTAS 替换的工程影响。
上线当天明明成功了,为什么第二天才失败?
2026-09-18 的日批成功,2026-09-19 的日批失败,rows written = 0。先按证据链走一遍:现象、证据、判断、定位、处理、验证、防复发。
第一次运行成功,究竟验证了哪些执行路径?
生命周期执行路径(Lifecycle Execution Path)
同一个任务会因为目标对象当前状态进入不同路径:目标对象不存在时走 initialize,已经存在时走 maintain。测试覆盖的是执行路径,而不是代码文件。
先认识这条日批任务
build.account-balance-snapshot.daily 每天把账户余额写成 AccountBalanceSnapshot:一行代表一个账户在一个快照日的余额,Grain 是 Account × snapshot_date,业务日期 business_date 同时也是 snapshot_date。
这份快照按业务日期组织写入。在这个教学案例里,可以把「当前业务日期的写入单元」理解为按 snapshot_date 组织的日期分区或等价写入单元;具体数据库如何实现,不是这一课的重点。
这条任务有一个生命周期分支:第一次运行时目标对象还不存在,之后每次运行目标对象都已经存在。两天的结果不同,先不要急着改代码,按证据一步步看。
- Day 1 = 2026-09-18,Day 2 = 2026-09-19。
- Grain:一行 = 一个账户 × 一个快照日。
- 这一课只处理「生成快照」这一段,不展开上游来源与下游消费。
同名目标表,是否还是同一个对象?
前面的故障调查聚焦「目标对象当前是否存在」以及 initialize / maintain 路径。这一段换一个问题:加工结果的名字相同,是否意味着结果对象的 identity、schema 和下游契约也保持不变?
下面用 `ads_deposit_balance_daily` 对照 DROP + CTAS 与固定表 TRUNCATE + INSERT。两者在正常执行时都可能得到正确数据;选择依据应是对象生命周期、schema 稳定性和运行场景,而不是 SQL 风格偏好。
- 通用事实:DROP 后重新 CREATE 是新的对象创建过程;CTAS 的列形状来自查询结果。
- 工程实践:固定表把 schema 契约放在目标定义里,但刷新、回滚和迁移仍需设计。
- 组织选择:授权恢复、依赖处理、发布门禁和 lineage 记录策略应按团队与平台约定决定。
先调查执行路径,再比较结果对象策略
先沿 7 步证据链对照两天运行,定位 initialize / maintain 差异;完成后继续切换 DROP + CTAS 与固定表刷新,以及正常成功、失败、schema 变化和 Retry 事件。
第一次运行掩盖了什么
Day 1 的目标对象不存在,任务走 initialize:创建目标对象时顺带初始化了 2026-09-18 的写入单元,然后写入快照。这条路径成立,所以当天成功。
Day 2 的目标对象已经存在,任务走 maintain。prepare 需要为 2026-09-19 准备写入单元,但它只检查了目标对象是否存在,没有确认当前 business_date 的写入单元是否就绪。缺陷第一次真正被执行,任务停在写入之前。
所以 Day 1 成功证明的是 initialize 路径,而不是 maintain 路径。代码里存在一个分支,不等于这个分支被运行过。
- initialize:目标对象不存在时,创建对象并初始化第一个日期写入单元。
- maintain:目标对象已存在时,维护后续业务日期。
- 同一个任务、同一段代码,两条路径需要分别验证。
这几个概念在前面已经讲过
business_date 与「任务凌晨运行、处理前一天数据」的时间语义见 05-1;Rerun 与幂等的区分见 05-4;Periodic Snapshot 与 Grain 见 02-4。这里只回忆一句:同一业务日期的重复执行,要按既定写入策略保持同一份结果,而不是叠加一份。