IT技术博客大学习 共学习 共进步
全部 移动开发 后端 数据库 AI 算法 安全 DevOps 前端 设计 开发者

我做了一个 AI 版的 StarRocks 升级风险扫描工具,直接帮我定位到一个风险

crossoverJie's Blog 2026-06-15 02:40:52 累计浏览 59 次
本机暂存

背景

最近在搞 StarRocks 的跨版本升级(3.3 → 3.5),中间踩了不少坑。我之前也写过一篇 StarRocks 升级注意事项记录了手动升级的流程,但那只是针对小版本(3.3.3 → 3.3.9)的升级。

跨大版本升级完全是另一回事——3.3 到 3.5 中间有 6000+ 个 commit,里面藏着各种不兼容变更:配置默认值变了、Session Variable 改了、Protocol 字段删了……人工逐个审查根本不现实,漏一个关键变更就可能导致生产事故。

于是我就想:能不能用 AI 来帮我干这活?经过一段时间的迭代,我用 Claude Code 手搓了一个 StarRocks 升级风险扫描工具(starrocks-upgrade skill),这篇文章就来聊聊它的设计原理。

现在升级之前会先执行一次 Skill,它首先会让你输入一些集群信息方便后面做具体的分析:

收集完成之后便会收集差异版本之间的 commit 信息开始分析,最终生成一个升级报告,给出一些潜在的风险,比如这个:

我们在升级之后确实遇到了这个问题,提前有了这份报告之后解决起来自然也要轻松许多。

问题域:为什么升级这么难

先说清楚我们要解决的核心问题。StarRocks 跨版本升级的难点不在于”升级操作”本身,而在于升级前不知道会发生什么

不兼容变更难以发现

版本间的配置项默认值变化、Session Variable 变更、BE 配置修改等,往往隐藏在几千个 commit 中。传统做法是人工阅读 Release Notes,但很多行为变更根本不会记录在 RN 里。

影响范围难以评估

一个配置项的默认值变化可能通过间接调用链产生连锁反应。比如 transform_type_prefer_string_for_varchar 从 false 变为 true,看起来只是改了个默认值,但它会通过 MV re-activation 间接导致物化视图失效。这种间接影响链靠肉眼根本发现不了。

集群特定风险无法量化

不同集群的配置(fe.conf/be.conf)、部署方式(K8s/VM)、规模(MV 数量、表数量)各不相同,通用的升级建议无法覆盖特定集群的风险。同样是默认值变了,你的集群如果已经在 conf 中覆盖了,风险就很低;但如果你用的恰好是旧默认值,升级后行为就直接变了。

现有方案的不足

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

特别是逐 PR 分析,这是最容易掉进去的坑。一个 PR 的 diff 只是变更的代码片段,你根本看不到变更所在的类与上下游调用关系。比如上面提到的 transform_type_prefer_string_for_varchar,PR diff 中只是修改了 Config.java 中的一个默认值,但你看不到 AnalyzerUtils.transformTableColumnType() 在读这个配置、MaterializedViewAnalyzer 调用了它、AlterJobMgr.reActivateMV() 又间接触发了 MV 重新解析——这条完整的间接影响链,只看 PR diff 是绝对看不出来的。

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

基于上面的分析,工具做了一个根本性的设计选择:必须在 StarRocks 源码根目录下运行,而不是逐个 PR 读取 GitHub 上的 diff。

这个选择的原因很简单:

能力逐 PR 分析源码全量扫描
识别配置项移除不行(已删除的行不会出现在 PR diff 中)可以——全量解析新旧版本的 Config.java,对比字段集合
追踪间接调用链不行——缺少源码上下文可以——在源码树中 grep 递归追踪
集群配置冲突检测不行——无法读取用户 conf可以——解析 cluster-profile.yaml 并与 Scanner 结果交叉对比
识别”默认值变更但用户未覆盖”不行可以——对比 conf 中的值与新旧默认值

简单来说:没有源码上下文,就没有深度分析。

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

这个工具的核心设计哲学是 prefer false positives over false negatives

原因很简单:升级风险的成本是非对称的。漏报一个不兼容变更可能导致生产事故,而误报只是增加了人工验证的工作量。所以工具采用了多层级扫描策略:11 个专项 Scanner 覆盖已知风险模式 + 逐 commit Tier 分类确保无遗漏。

整体架构

整个工具的工作流分为四个阶段,先看一张全局视图:

Phase 1:数据收集

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

Git Commit Diff 采集

通过 git log branchA..branchB 获取目标分支独有的 commits,然后对每个 commit 做分类。这里有个关键优化——使用自定义分隔符(SOH/STX)通过单次 git log 调用获取所有 commit 的完整信息,避免 N+1 查询。

Commit Tier 分类

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

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

这样 HIGH/MEDIUM 的 commit 得到深度分析,LOW/SKIP 不浪费资源。

11 个专项 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.java 的解析是整个工具中最复杂的部分。

Java 注解可能跨多行:

@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 前缀)

正则 CONF_(m?\w+)\((\w+),\s*"([^"]*)"\) 一把就能提取出来,注意 m 前缀表示 mutable,可运行时修改。

集群配置冲突检测

这是我觉得最有用的功能。不同场景下同一个默认值变化的风险完全不同:

场景示例风险
配置已移除 + 你的 conf 中有mysql_service_nio_enabled 已删除,你 conf 中有 = trueHIGH — 启动报错
默认值变化 + 你使用旧默认enable_load_volume_from_conf true→false,你 conf 中 = trueMEDIUM — 你的覆盖生效,但需决定是否跟随
默认值变化 + 你有自定义值你 conf 中设了 = custom_valueLOW — 你的覆盖优先
默认值变化 + 你未覆盖mysql_server_version 5.1.0→8.0.33,你 conf 中没有HIGH — 自动采用新默认值

这种精确区分比泛泛地说”某个配置默认值变了”有用得多。

部署方式感知

工具还会根据集群的部署方式生成特定风险提示:

比如 K8s 环境下,FE Pod 重启会触发 MV re-activation,如果有 MV 相关代码变更,可能导致 schema 不兼容;VM 环境下则更关注升级顺序(BE 先 FE 后)。

Phase 2:Commit Diff 分析

Phase 1 保存了 HIGH/MEDIUM commit 的完整 diff。Phase 2 由 AI Agent 执行,利用并行 Subagent 对 commit 进行深度兼容性分析。

由于跨版本 diff 的 commit 数量通常很大(3.3→3.5 有 1361 个 HIGH tier commit),逐个串行分析不现实。所以按模块分组,每组 5-8 个 commit 分配给一个并行 Subagent:

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

Phase 3:深度影响分析

Phase 2 的输出 + Phase 1 的 Scanner 发现中,所有 CRITICAL/HIGH 级别的发现需要进一步深度分析。每个(或每批相关的)发现分配一个并行 Subagent,在源码树中 grep 追踪调用链。

这是工具最独特的设计之一——系统生命周期入口追踪。一个配置变更可能不直接被生命周期代码引用,但通过间接调用链到达:

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

如果不追踪这条间接路径,就会漏掉”FE 重启后 MV re-activation 失败”这个关键风险。

Phase 4:报告综合

将 Phase 1-3 的所有分析结果综合为一份结构化的中文升级报告。

报告的核心设计原则:

  1. INCOMPATIBLE CHANGES 置顶:最关键的信息放在最前面,按 CRITICAL > HIGH 排序
  2. 按触发时机分类报错场景:FE 重启后 / CN 重启后 / 日常查询 / 升级过程中
  3. 集群特定的冲突检测:只有与用户集群配置相关的冲突才展示
  4. 可操作的 Upgrade Checklist:每个步骤都是具体的、可执行的

数据流全图

把 Phase 1 的数据流串起来看会更清晰:

统一影响模型

所有 Scanner 的发现都使用统一的四维影响模型:

维度含义触发条件示例
data影响现有数据transform_type_prefer_string_for_varcharmax_varchar_length
behavior相同 SQL 可能返回不同结果sql_modemysql_server_version
operational需要配置/运维变更任一 HIGH_RISK 配置变更
rolling_upgrade混合版本集群可能中断protocol_field_removedstorage_format_changed

每个发现都附带四维评估,便于按维度筛选和汇总。

总结

这个工具的设计思路可以归结为以下几点:

  1. 源码是真理:所有分析都建立在完整的源码树上,而不是 GitHub API 返回的 PR diff 片段。没有源码上下文,就没有深度分析。

  2. 分层处理:不是所有 commit 都值得深度分析,Tier 分类的分层策略确保关键 commit 得到深度分析,低风险 commit 不浪费资源。

  3. 专项 Scanner + AI Agent 的组合:Python 脚本做确定性的数据收集和模式匹配(11 个 Scanner),AI Agent 做不确定性的深度分析(调用链追踪、影响评估)。各取所长。

  4. 集群特定:不是给出通用建议,而是结合用户实际的 fe.conf/be.conf,精确识别集群特定风险。

  5. 宁可误报也不漏报:升级风险的成本是非对称的,漏报的代价远大于误报。

当然也有局限性:Protocol/Parser Scanner 精度有限、间接调用链追踪依赖 AI Agent 的能力、无法检测运行时行为变化、大仓库性能问题(6000+ commit 需要 30 分钟以上)。这些也是后续改进的方向。

如果你也在维护 StarRocks 集群并且经常需要跨版本升级,可以试试这个工具。至少在我这边,它帮我发现了好几个 Release Notes 里没提到的不兼容变更。

对于这种大型项目,存在复杂的上下文分析完全是现在 LLM 擅长的地方,非常适合拿来做这种以前的人工体力活。

同分类推荐文章

  1. 硬件故障后数据文件大小不对故障处理—Oracle碎片扫描恢复 (2026-06-07 18:21:47)
  2. 如何在Hive SQL中构造临时表用于和其它的表做关联? (2026-05-29 20:07:00)
  3. asm dd 10M导致system文件部分坏块修复 (2026-05-22 00:23:15)

查看更多 数据库 文章 →

建议继续学习

  1. 智能输入法软件的社会责任问题 (累计阅读 3,345)
  2. 浅谈 WHR 全历史排名 (累计阅读 2,842)
  3. 祢衡这个人 (累计阅读 1,595)
  4. AI Agent Orchestrator Landscape Report (累计阅读 156)
  5. 「置顶」我做了什么 (累计阅读 118)
  6. 中文 Markdown 强调标记的渲染问题 (累计阅读 83)
  7. SmartPerfetto 架构文章 Q&A:8 个深度技术问答 (累计阅读 98)
  8. Vibe Coding 的安全风险与应对策略 (累计阅读 42)
  9. 了解 Claude Code 的提示词工程 (累计阅读 52)
  10. StarRocks 物化视图创建与刷新全流程解析 (累计阅读 30)