3. 数据资产版本控制策略

在 Azure DataOps 的持续交付体系中,数据资产版本控制是整条流水线的起点。所谓“数据资产”,并不只是数据本身,而是围绕数据流动所产生的一切可版本化产物:SQL 脚本、数据管道定义(如 ADF 的 JSON 模板)、Databricks Notebook、Schema 定义、数据质量规则、基础设施即代码(IaC)模板,以及与之配套的配置与参数文件。把这些资产纳入 Git 管理,意味着每一次变更都有迹可循、可回滚、可评审,也意味着发布流程可以建立在确定性的版本快照之上。

一、仓库结构:按“资产类型 + 环境”分层

一个可维护的 Azure DataOps 仓库,通常不会把所有文件平铺在根目录。推荐采用“按资产类型分目录、按环境分参数”的结构,让代码与配置分离,避免环境差异污染主干逻辑。下面是一个可直接参考的仓库骨架示例:

data-platform-repo/
├── pipelines/                 # ADF 管道定义(导出为 JSON)
│   ├── pl_ingest_sales.json
│   └── pl_transform_daily.json
├── notebooks/                 # Databricks Notebook
│   └── nb_silver_cleansing.py
├── sql/
│   ├── ddl/                   # 建表与 Schema 变更
│   │   └── dim_customer.sql
│   └── dml/                   # 存储过程与转换逻辑
│       └── sp_load_fact_sales.sql
├── dataquality/               # 数据质量规则
│   └── dq_sales_rules.json
├── infra/                     # IaC(Bicep / Terraform)
│   └── main.bicep
├── config/
│   ├── dev/params.json
│   ├── test/params.json
│   └── prod/params.json
└── .azure-pipelines/
    └── ci-cd.yml

这种结构的关键在于:逻辑与参数分离。管道 JSON、SQL 脚本、Notebook 属于逻辑资产,放在各自目录;环境相关的连接串、存储账户名、密钥引用放在 config/<env>/ 下。发布时由流水线按目标环境注入对应参数,而不是在脚本里硬编码环境差异。这样主干分支始终代表“逻辑真相”,环境差异只体现在参数层。

二、分支模型:以 trunk-based 为主、release 分支为辅

数据平台团队常见两种分支模型:Git Flow 与 trunk-based。对于持续交付节奏较快的数据平台,更推荐以 trunk-based 为主:main 分支始终保持可发布状态,功能开发在短生命周期的 feature/* 分支上进行,通过 Pull Request 合并回 main。当需要为某个生产版本提供稳定支持时,再从 main 切出 release/* 分支,仅接受缺陷修复。

分支模型的核心约束有三条:第一,main 分支受保护,禁止直接推送,必须经过 PR 与至少一名评审;第二,feature 分支生命周期尽量短(建议不超过 3 天),减少合并冲突;第三,任何进入 main 的变更都必须通过 CI 校验(SQL 语法检查、管道 JSON 校验、单元测试)。这三条约束共同保证“主干即真相”。

三、SQL 脚本与数据管道的版本化要点

SQL 脚本的版本化不只是“把 .sql 文件放进 Git”。对于 DDL 变更,建议采用迁移脚本(migration script)方式:每个 Schema 变更对应一个带序号或时间戳的脚本,例如 V001__create_dim_customer.sql、V002__add_column_to_fact_sales.sql。脚本一旦合并入 main 就不再修改,后续变更通过新脚本追加。这样任何环境都能按顺序重放,得到一致的 Schema 状态。

数据管道(以 ADF 为例)的版本化有一个特殊点:ADF 在 Azure 门户中的编辑会直接写入服务端,容易与 Git 脱节。正确做法是启用 ADF 的 Git 集成,让门户编辑自动同步到指定分支;或者采用“代码优先”方式,将管道 JSON 作为源文件管理,通过 CI/CD 发布到目标环境。无论哪种方式,都要保证服务端状态与 Git 状态一致,避免出现“门户改了但 Git 没记录”的漂移。

下面这张图展示了从本地开发到多环境发布的版本控制与分支协作关系,重点体现“逻辑资产在主干、参数按环境注入、发布由分支触发”的结构:

开发与分支协作 开发者本地 feature/* 分支 Pull Request 评审 + CI 校验 main 主干 始终可发布 release/* 稳定版本维护 Git 仓库结构 data-platform-repo pipelines/ ADF JSON notebooks/ Databricks sql/ ddl + dml dataquality/ 规则 infra/ Bicep / TF config/ dev|test|prod 环境发布 Dev 自动部署 Test 审批后部署 Prod 手动批准 发布时按目标环境注入 config/<env>/params.json 逻辑资产来自 main 分支快照 · 环境差异仅体现在参数层 代码/分支流向 环境晋级

四、版本化带来的可追溯与回滚能力

当 SQL 脚本、管道定义、Notebook 都进入 Git 后,每一次发布都可以对应到一个明确的 commit SHA。这意味着:生产环境出现问题时,可以快速定位“是哪次变更引入的”;需要回滚时,可以基于上一个稳定 commit 重新发布,而不是靠人工回忆改了什么。对于数据平台而言,这种可追溯性尤其重要,因为 Schema 变更、管道逻辑调整往往会影响下游报表与模型,回滚窗口越短,业务影响越小。

建议在每次发布时,将 commit SHA、发布环境、发布时间、发布人记录到发布日志中。这样当数据异常发生时,可以快速把“数据问题”与“代码变更”关联起来,缩短排障路径。

五、常见反模式与规避建议

  • 直接在门户改管道、不同步 Git:导致服务端与仓库漂移。应启用 Git 集成或坚持代码优先发布。
  • SQL 脚本就地修改:已合并的迁移脚本被覆盖,环境间 Schema 不一致。应坚持“追加新脚本、不改旧脚本”。
  • 环境参数硬编码在脚本里:同一份脚本无法跨环境复用。应把环境差异抽到 config/<env>/。
  • feature 分支长期不合并:冲突累积、评审困难。应控制分支生命周期,小步合并。

总结来说,数据资产版本控制策略的核心是三点:结构上逻辑与参数分离、分支上主干保持可发布、变更上以追加式迁移脚本保证可重放。做到这三点,后续的 CI/CD 流水线才有稳定的输入,发布才具备确定性与可回滚性。