从 6000+ Commit 中识别升级风险:一个 StarRocks AI 升级扫描工具的实现

摘要:
本文转载自 StarRocks 社区贡献者 crossoverJie。

在 StarRocks 跨版本升级过程中,如何快速识别潜在兼容性风险,一直是许多团队面临的现实问题。近期,crossoverJie 基于 Claude Code 开发了一款 StarRocks 升级风险扫描工具,通过 AI 辅助分析升级过程中的配置变更、兼容性影响及潜在风险点。

本文将分享该工具的设计思路与实现过程,希望能为正在规划 StarRocks 升级的用户提供参考。

背景

最近在进行 StarRocks 跨版本升级(3.3 → 3.5)时,对升级风险评估这件事有了不少新的思考。

与小版本升级不同,3.3 到 3.5 之间包含 6000+ 个 Commit,涉及配置项、Session Variable、协议字段等大量变更,依靠人工逐项审查既耗时又容易遗漏关键风险。

于是我开始尝试借助 AI 来辅助完成升级风险分析,并基于 Claude Code 开发了一款 StarRocks 升级风险扫描工具——starrocks-upgrade Skill。本文将分享它的设计思路与实现过程。

项目地址:https://github.com/crossoverJie/skills/blob/main/skills/starrocks-upgrade/SKILL.md

收集完集群信息后,Skill 会分析目标版本之间的 Commit 变更,并生成一份升级风险报告,识别升级过程中可能存在的潜在风险,例如:

后续实际升级时,确实遇到了报告中提示的问题。由于提前有了这份风险报告,问题定位和处理过程也顺利了许多。

升级风险分析:到底难在哪里?

先明确一个问题:StarRocks 跨版本升级的难点并不在于升级操作本身,而在于升级前很难准确评估潜在影响。

不兼容变更难以发现

版本间的配置项默认值变化、Session Variable 调整、BE 配置修改等,往往分散在数千个 Commit 中。传统做法主要依赖 Release Notes,但许多行为层面的变更并不会完整记录在 Release Notes 里。

影响范围难以评估

一个配置项的默认值变化,可能通过复杂的调用链产生连锁反应。

例如, transform_type_prefer_string_for_varcharfalse 变为 true ,表面上只是一个默认值调整,但实际可能通过 MV Re-activation 机制间接导致物化视图失效。这类间接影响往往跨越多个模块,仅依靠人工分析很难完整识别。

集群特定风险无法量化

不同集群在配置(fe.conf、be.conf)、部署方式(Kubernetes、VM)以及规模(MV 数量、表数量)等方面存在较大差异,通用的升级建议很难覆盖所有场景。

同样是默认值发生变化,如果相关配置已经在集群中显式覆盖,风险可能非常有限;但如果业务依赖旧版本默认行为,升级后则可能直接导致运行结果发生变化。

现有方案的不足

常见的升级风险评估方式主要有以下几种:

方案 局限性
人工阅读 Release Notes 信息不完整,许多行为变更不会记录在 Release Notes 中
git log --oneline A…B 只能看到 commit 列表,无法判断兼容性风险
CI/CD 自动化测试 只能验证功能正确性,无法发现配置冲突、运维影响
逐个 PR 阅读分析 分析片面——只看 PR diff 无法了解调用链和上下游影响

其中,逐 PR 分析尤其容易让人产生误判。

单个 PR 的 Diff 只能展示局部代码变更,而升级风险往往来自跨模块、跨调用链的间接影响。例如前文提到的 transform_type_prefer_string_for_varchar ,PR 中看起来只是修改了 Config.java 的一个默认值,但其实际影响可能涉及 AnalyzerUtils.transformTableColumnType()MaterializedViewAnalyzer 以及 AlterJobMgr.reActivateMV() 等多个模块,并最终导致 MV 重新解析。

这类跨模块的影响链路,仅依靠阅读 PR Diff 很难完整识别。

核心设计选择:源码全量扫描

基于前面的分析,这个工具做出了一个关键设计选择: 必须在 StarRocks 源码根目录下运行,而不是依赖 GitHub 上的 PR Diff 进行分析。

原因如下:

能力 逐 PR 分析 源码全量扫描
识别配置项移除 难以实现,已删除代码通常不会出现在 PR Diff 中 可直接对比新旧版本源码中的配置定义
追踪间接调用链 缺少完整上下文,难以分析 可基于完整源码追踪调用关系
集群配置冲突检测 无法获取用户实际配置 可结合集群配置进行交叉分析
识别"默认值变更但用户未覆盖" 难以判断实际影响 可对比用户配置与版本默认值差异

简单来说, 没有完整的源码上下文,就很难进行深度的升级风险分析。

设计哲学:宁可误报,也不漏报

这个工具遵循一个核心原则: 宁可增加人工确认成本,也尽量避免遗漏潜在风险。

原因在于升级风险的成本并不对等。一次误报带来的影响,通常只是增加一些人工排查和验证工作;而遗漏一个关键的不兼容变更,则可能直接影响生产环境的稳定性。

基于这一原则,工具采用了多层级扫描策略:一方面通过 11 个专项 Scanner 覆盖已知风险模式,另一方面结合逐 Commit 分层分析(Tier Classification)。

整体架构

整个工具的工作流程可以分为四个阶段,下面先通过一张架构图了解整体流程:

Phase 1:数据收集

这是整个工具的基础,由 starrocks_upgrade.py 实现。它要做的事情很多:

数据收集是整个工具的起点,由 starrocks_upgrade.py 负责实现。在这一阶段,工具会尽可能收集升级分析所需的上下文信息,包括:

Git Commit Diff 采集

工具首先通过 git log branchA..branchB 获取目标版本之间新增的 Commit,并对每个 Commit 进行分类分析。

为了提高扫描效率,工具使用自定义分隔符(SOH/STX),通过一次 git log 调用获取所有 Commit 的完整信息,避免逐 Commit 查询带来的 N+1 问题。

Commit Tier 分类

不是所有 commit 都需要深度分析。工具把 commit 分成四级:

并不是所有 Commit 都需要同等程度的分析,工具将 Commit 划分为四个等级:

Tier 匹配规则 处理方式
SKIP test/docs/build 目录;commit 前缀为 build/chore/ci/style 仅统计数量
HIGH 核心路径:FE 优化器/执行器/SQL 解析、BE runtime/storage、Protocol/IDL 保留完整 Diff 并进行深度分析
MEDIUM 业务路径:连接器/认证/权限;feat/fix 类型的源码变更 保留完整 Diff 并进行常规分析
LOW 其他所有变更 仅保存元数据

通过这种分层策略,工具能够将分析资源集中在真正可能影响兼容性的 Commit 上,将有限的分析资源优先投入到最有可能产生兼容性风险的变更上。

11 个专项 Scanner

专项 Scanner 是整个工具的核心能力,用于从不同维度识别升级过程中可能存在的兼容性风险。目前共覆盖 11 类风险场景:

FE 侧:

  • Config Scanner — 扫描 Config.java 中的 @ConfField 配置项变更

  • Session Variable Scanner — 扫描 SessionVariable.java 中的 @VarAttr 变量变更

  • System Variable Scanner — 扫描 GlobalVariable.java

  • Auth Scanner — 扫描 AuthenticationManager.javaPrivilegeManager.java

BE 侧:

  • BE Config Scanner — 扫描 config.h 中的 CONF_* 宏定义

  • Storage Format Scanner — 扫描 segment_format.htablet_meta.h

IDL/协议:

  • Protocol Scanner — 扫描 .thrift / .proto 文件变更

  • Parser Scanner — 扫描 StarRocksParser.g4AstBuilder.java

数据/类型:

  • Charset () /Collation Scanner — 扫描 Collation*.java

  • Type System Scanner — 扫描 ScalarType.java / Column.java

  • MV Scanner — 扫描 MaterializedView.javaMVRefreshParams.java

虽然扫描对象各不相同,但所有 Scanner 都遵循相同的工作模式:

Config Scanner 的状态机解析

Config Scanner 是整个工具中相对复杂的一部分,主要原因在于 Config.java 的解析并不是简单的文本匹配。

以 Java 注解为例, @ConfField 可能跨多行定义:

@ConfField(mutable = true, comment = "Whether to prefer string type "
        + "for fixed length varchar column in materialized view creation/ctas")
public static boolean transform_type_prefer_string_for_varchar = true;

所以解析器采用了 逐行状态机 模式:

工具通过状态机跟踪 () 的配对关系,将跨多行的注解拼接为完整结构后再进行解析,从中提取 mutablecomment 等属性。

这种方式虽然实现更复杂,但相比正则匹配能够更可靠地处理各种格式和边界情况。

BE Config 解析

BE 侧的配置主要通过 C++ 宏进行声明,因此需要采用完全不同的解析策略。

CONF_Bool(datacache_auto_adjust_enable, "false")     // 不可运行时修改
CONF_mBool(lake_enable_alter_struct, "true")          // 可运行时修改 (m 前缀)

由于 BE 配置定义相对规整,工具通过正则表达式 CONF_(m?\w+) $$(\w+),\s*"([^"]*)$$ 即可提取配置项名称、类型和默认值等信息。其中, m 前缀表示该配置项支持运行时动态修改(mutable)。

集群配置冲突检测

这是整个工具中最实用的功能之一。

例如,同样是配置项变更,不同集群环境下的风险等级可能完全不同:

场景 示例 风险
配置项已删除,且用户显式配置 mysql_service_nio_enabled 已删除,但 conf 中仍设置为 true HIGH:启动或运行异常风险
默认值变化,用户显式覆盖 enable_load_volume_from_conf 默认值由 true 变为 false,但 conf 中已配置为 true MEDIUM:当前行为保持不变,但需评估后续是否跟随新默认值
默认值变化,用户使用自定义值 用户已设置 custom_value LOW:用户配置优先,影响较小
默认值变化,用户未覆盖 mysql_server_version 默认值由 5.1.0 调整为 8.0.33,且未在 conf 中配置 HIGH:升级后将自动采用新默认值

这种分析方式相比简单提示“某个配置项发生了变化”更有价值

部署方式感知

除了源码和配置分析之外,工具还会结合集群的实际部署方式,生成针对性的风险提示。

例如,在 Kubernetes 环境下,FE Pod 重启可能触发 MV Re-activation。如果升级版本包含 MV 相关代码变更,则需要重点关注 Schema 兼容性问题。

而在 VM 环境下,升级顺序往往更加关键,例如部分场景需要遵循 BE 先、FE 后 的升级策略。

Phase 2:Commit Diff 分析

在 Phase 1 中,工具会保存 HIGH/MEDIUM 等级 Commit 的完整 Diff。进入 Phase 2 后,AI Agent 会基于这些 Diff 进行深度兼容性分析。

由于跨版本升级涉及的 Commit 数量通常很大,例如 3.3 → 3.5 中包含 1361 个 HIGH Tier Commit,逐个串行分析并不现实。因此,工具会按照模块对 Commit 进行分组,并将每组 5–8 个 Commit 分配给并行 Subagent 处理:

每个 Subagent 输出结构化的分析结果: compatibility_impactimpact_typeseverityerror_scenarioreproductionrollback

Phase 3:深度影响分析

经过 Phase 2 的兼容性分析,以及 Phase 1 中各类 Scanner 的扫描后,工具会筛选出所有 CRITICALHIGH 级别的风险项,进入深度影响分析阶段。

对于每个高风险发现(或一组关联发现),工具会分配一个并行 Subagent,通过 grep 和源码追踪的方式分析调用链。

生命周期入口追踪

这是整个工具中最有特点的设计之一。很多升级风险并不是由代码变更直接触发的,而是通过多层调用链间接传递

transform_type_prefer_string_for_varchar (Config)
  └─ AnalyzerUtils.transformTableColumnType() (直接调用方)
       └─ MaterializedViewAnalyzer (间接调用方)
            └─ AlterJobMgr.reActivateMV() (系统生命周期入口: FE 重启时触发)

如果无法追踪这条间接调用链,就很难识别“FE 重启后 MV Re-activation 失败”这类关键风险。

Phase 4:报告综合

最后,工具会将 Phase 1 至 Phase 3 的分析结果进行汇总,生成一份结构化的中文升级风险报告。

报告遵循以下设计原则:

  1. 关键风险优先展示: 将不兼容变更(Incompatible Changes)置于报告最前面,并按照 CRITICAL → HIGH 的优先级排序

  2. 按触发时机分类报错场景: 例如 FE 重启后、CN 重启后、升级过程中、日常查询阶段等。

  3. 结合集群环境进行筛选: 仅展示与当前集群配置、部署方式或运行环境相关的风险,避免无关告警干扰判断。

  4. 提供可执行的升级检查清单: 针对识别出的风险项生成具体的 Upgrade Checklist,帮助用户在升级前完成必要检查和验证工作。

数据流全图

将前面各个阶段串联起来,整个工具的数据流如下:

统一影响模型

为了将不同 Scanner 的发现统一归类和评估,工具设计了一套四维影响模型。

维度 含义 触发条件示例
Data 影响现有数据 transform_type_prefer_string_for_varchar、max_varchar_length
Behavior 相同 SQL 可能返回不同结果 sql_mode、mysql_server_version等变更
Operational 需要配置/运维变更 任一 HIGH_RISK 配置变更
Rolling Upgrade 混合版本集群可能中断 protocol_field_removed、storage_format_changed

每个风险项都会附带对应的影响维度标签,便于后续按类型进行筛选、汇总和优先级排序。

总结

整个工具的设计思路可以概括为以下几点:

  1. 源码优先: 所有分析都建立在完整源码上下文之上,而不是依赖 GitHub API 返回的 PR Diff。只有结合类定义、调用关系和模块依赖,才能准确评估升级风险。

  2. 分层分析: 并非所有 Commit 都需要同等程度的关注。通过 Tier 分类机制,将分析资源集中在最有可能产生兼容性影响的变更上,在分析深度与效率之间取得平衡。

  3. 规则扫描与 AI 分析结合: 由 Scanner 负责确定性的数据收集和风险识别,由 AI Agent 负责调用链追踪、影响分析和风险评估,两者协同完成升级风险分析。

  4. 结合实际集群环境: 风险评估不仅关注版本变更本身,还结合用户实际的 fe.confbe.conf 以及部署环境进行分析,从而识别真正需要关注的问题。

  5. 宁可误报,也不漏报: 对于升级场景而言,一次误报通常只会增加少量验证成本,而一次漏报则可能带来生产风险。

当然,这个工具目前仍有不少局限性。例如:

  • Protocol Scanner 和 Parser Scanner 的分析精度仍有提升空间;

  • 间接调用链追踪的效果依赖 AI Agent 的分析能力;

  • 无法直接识别运行时行为变化带来的影响;

  • 在大型代码仓库中,分析耗时仍然较长,例如跨越 6000+ Commit 的升级分析通常需要 30 分钟以上。

这些问题也是后续持续优化的方向。

如果你也在维护 StarRocks 集群,并且经常需要进行跨版本升级,不妨试试这个工具。至少在我的实践中,它已经帮助发现了多个 Release Notes 中未提及的不兼容变更。

[1]StarRocks 升级注意事项: https://crossoverjie.top/2025/03/14/starrocks/StarRocks-upgrade/

[2]starrocks-upgrade skill: https://github.com/crossoverJie/skills/blob/main/skills/starrocks-upgrade/SKILL.md