首页/数据/数据工程与 ETL 速查/catchup 补跑行为控制

catchup 补跑行为控制

catchup 决定新上线的 DAG 是否补齐 start_date 到当前的所有周期:开启会一次性生成大量历史周期任务,关闭则从当前之后开始。

catchup 是什么

catchup 决定一个 DAG 上线时要不要「补历史」:开启后调度器会从 start_date 起把每个调度周期都生成一次运行,一直追到当前;关闭则只从上线之后的时间点开始跑。这个开关看起来只是个小参数,但它决定了上线瞬间会给集群带来多少任务——start_date 写成年初、周期是每天、又开了 catchup,等于一次性放出几百个 DagRun。

基本信息

catchup=True补齐 start_date 以来的每个调度周期
catchup=False跳过历史,只跑当前及之后
配套参数max_active_runs 限制同时运行的周期数
适用建议历史数据无需回刷时关闭;需要补历史时用受控的 backfill
影响范围仅对新上线的 DAG 或修改 restart_date 后生效
版本差异Airflow 2.x 用 catchup 参数,3.x 中改名后有对应设置

Airflow DAG 参数

Airflow DAG 参数
from datetime import datetime
from airflow import DAG

dag = DAG(
    'daily_orders',
    start_date=datetime(2026, 1, 1),
    schedule='0 2 * * *',
    catchup=False,          # 上线后不补历史
    max_active_runs=1,      # 同时只允许一个周期在跑
    default_args={'retries': 2},
)

典型使用场景

  • 新 DAG 首次上线:确认历史已由离线任务补过,用 catchup=False 直接接当天
  • 需要追历史:保留 catchup 但先把 max_active_runs 设为 1,观察资源后再放开
  • 上线演练:在测试环境打开 catchup 看任务密度,再决定生产配置
  • 误开排查:发现集群突然多出大量 DagRun,先确认是不是某个新 DAG 开了 catchup
  • 口径重刷:不用 catchup 全量追,改用 backfill 指定区间分批重跑
  • 关闭后的验证:上线当天手动触发一次运行,确认调度周期与分区口径符合预期

参数组合影响

catchupmax_active_runs结果
True未限制瞬间生成大量周期,抢占 worker
True1按周期串行追平,资源可控但耗时长
False任意跳过历史,只跑之后的时间点
False + backfill由命令控制按指定区间受控补数
开启 catchup 且 start_date 很早时会瞬间创建成百上千个 DagRun,要配合 max_active_runs 与并发限制。
catchup 只在 DAG 首次被调度器感知时起作用;已经跑过的 DAG 改这个参数不会重新生成历史周期,需要补历史仍要走 backfill。
把 start_date 写在 DAG 文件里而不是每个任务里,避免同一 DAG 内不同任务计算出的周期不一致。

易错点

  • 忘了设置 catchup,上线即触发数月历史任务,打满集群
  • 关掉 catchup 后又要补历史时,应使用 backfill 指定区间,而不是改回 catchup 全量重跑
  • start_date 写成很久以前且带时区混用,周期计算与预期不一致
  • 开了 catchup 却不限制并发,多个历史周期同时写同一张表互相覆盖
  • 以为改 catchup 就能重跑历史,实际需要先删除对应 DagRun 或用 backfill

数据来源与参考

  • Apache Airflow 官方文档:Catchup 与 Backfill 说明
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌