You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

dbt v1.9.8中check策略check_cols: all新增列时快照失败(回归问题)

dbt快照check策略+check_cols: all时新增源表列执行失败的临时解决方案

问题背景

使用check快照策略并设置check_cols: all时,给源模型新增列会导致dbt snapshot执行失败,抛出invalid identifier 'SNAPSHOTTED_DATA.NEW_COLUMN_NAME'错误。dbt会在新列被添加到快照表之前尝试从现有快照表中查询该列,直接中断构建。这是已修复问题#3146的回归,目前已提交新bug报告#11735。

临时解决办法

除了手动执行ALTER TABLE新增列或临时切换快照策略外,还有以下可行方案:

1. 临时指定明确的check_cols列表

将当前快照表已存在的列明确列在check_cols中,跳过新列,执行一次快照后再改回check_cols: all:

snapshots:
  - name: my_snapshot
    config:
      unique_key: id
      strategy: check 
      check_cols: [id, name, age] # 仅包含快照表已有的列

执行dbt snapshot成功完成后,再将配置改回check_cols: all,后续快照即可正常处理schema变更。

2. 自定义宏处理列引用

通过覆盖dbt的快照宏,在生成对比SQL时对缺失的列做兼容处理。以Snowflake为例,修改snapshot_check_strategy相关宏,在引用快照表列时自动适配缺失列:

{% macro snapshot_check_strategy(node, snapshotted_rel, current_rel, config, target_exists) %}
  {% set check_cols = config.get('check_cols') %}
  {% if check_cols == 'all' %}
    {% set check_cols = current_rel.columns | map(attribute='name') | list %}
  {% endif %}

  {% set snapshotted_col_names = snapshotted_rel.columns | map(attribute='name') | list %}
  {% set comparison_pairs = [] %}
  
  {% for col in check_cols %}
    {% if col in snapshotted_col_names %}
      {% do comparison_pairs.append(
        (col, snapshotted_rel ~ "." ~ col, current_rel ~ "." ~ col)
      ) %}
    {% else %}
      {% do comparison_pairs.append(
        (col, "NULL AS " ~ col, current_rel ~ "." ~ col)
      ) %}
    {% endif %}
  {% endfor %}

  # 后续对比逻辑使用处理后的comparison_pairs生成SQL
{% endmacro %}

将上述宏放在项目的macros目录下,dbt执行时会优先使用自定义宏,避免查询不存在的列报错。

3. 预钩子自动同步schema

编写自定义宏,在快照执行前自动对比源表与快照表的列,新增缺失的列:

{% macro sync_snapshot_columns(snapshot_name, source_model) %}
  {% set source_cols = adapter.get_columns_in_relation(ref(source_model)) %}
  {% set snapshot_cols = adapter.get_columns_in_relation(ref(snapshot_name)) %}
  {% set source_col_names = source_cols | map(attribute='name') | list %}
  {% set snapshot_col_names = snapshot_cols | map(attribute='name') | list %}
  {% set missing_cols = source_col_names | reject('in', snapshot_col_names) | list %}

  {% for col in missing_cols %}
    {% set col_def = source_cols | selectattr('name', 'equalto', col) | first %}
    {% set alter_stmt = "ALTER TABLE " ~ ref(snapshot_name) ~ " ADD COLUMN " ~ col ~ " " ~ col_def.data_type %}
    {% do run_query(alter_stmt) %}
  {% endfor %}
{% endmacro %}

然后在快照配置中添加预钩子:

snapshots:
  - name: my_snapshot
    config:
      unique_key: id
      strategy: check 
      check_cols: all
      pre-hook: "{{ sync_snapshot_columns('my_snapshot', 'your_source_model_name') }}"

这样每次执行快照前会自动同步缺失的列,无需手动操作。

补充说明

  • 该问题仅在dbt-core 1.9.x版本出现,建议关注官方issue的修复进度;
  • 若团队频繁进行schema变更,预钩子同步的方案可以长期使用,减少手动操作成本。

内容的提问来源于stack exchange,提问作者omar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 22:23:17