)
TDengine 升级兼容性检查项全解滚动升级与冷升级的验证体系compat-check【免费下载链接】TDengineHigh-performance, scalable time-series database designed for Industrial IoT (IIoT) scenarios项目地址: https://gitcode.com/GitHub_Trending/tde/TDengine导读TDengine 版本迭代频繁跨版本升级尤其滚动升级后能否保证写入、查询、订阅、权限、索引与聚合对象完整无损是生产环境最关心的问题之一。本文以仓库内 test/tools/compat-check/docs/check.md 的“升级兼容性检查项总览”为主线结合 test/tools/compat-check 工具的完整实现逐项拆解滚动升级-r与冷升级默认模式下每条检查项的含义、判定逻辑与底层实现并给出INFORMATION_SCHEMA白名单机制的完整用法。读完本文你将能独立读懂 compat-check 的检查报告、配置检查阈值、处理白名单并把这套验证体系接入自己的升级 CI 流程。1. 为什么需要升级兼容性检查TDengine 集群由 dnode / mnode / vnode 等多类节点组成升级不只是替换二进制还涉及元数据、WAL、数据文件、订阅位点TMQ offset、聚合对象TSMA/RSMA、流计算Stream与用户权限的跨版本迁移。任何一个环节在升级后“悄悄变化”都可能在线上造成隐性故障。test/tools/compat-check 是一个在单台 Linux 机器上自动完成这一验证的测试框架它在本机启动一个 3 节点集群先在基准版本上构造写入/查询/订阅负载与各类资源再执行冷升级或滚动升级最后逐项验证数据完整性与资源保持情况。文档 check.md 正是这份验证体系的“检查项清单总览”。2. 检查项对照表完整继承以下表格即 check.md 的核心内容列出全部检查项以及它们在滚动升级-r与冷升级默认下的覆盖情况检查项滚动升级 (-r)冷升级默认备注升级过程本身✅✅所有节点均完成版本替换升级期间持续写入✅—冷升级期间集群停机无写入升级期间持续查询✅—同上升级期间持续订阅✅—同上升级后写入无失败批次✅✅升级后查询无失败批次✅✅升级后订阅无长时间中断✅✅默认超时 180 秒订阅消费行数 写入行数✅✅test_user 账号可正常认证✅✅test_user 权限集合不变✅✅Tag Index 保持存在✅✅TSMA 保持存在✅✅仅基准版本 ≥ 3.3.6.0 时执行Stream 保持运行✅✅仅基准版本 ≥ 3.3.7.0 时执行RSMA 保持存在✅✅仅基准版本 ≥ 3.3.8.0 时执行INFORMATION_SCHEMA 无意外变化✅✅需加-S参数启用支持白名单豁免几点关键说明源自 check.md 的“说明”小节滚动升级后台写入、查询、订阅在升级全程持续运行能捕获节点切换瞬间的服务中断因此“升级期间持续写入/查询/订阅”三项只有滚动升级会验证。冷升级集群完全停止后再升级再启动后台负载仅在升级完成后运行侧重验证数据与资源完整性。-S/--check-sysinfo两种升级模式均支持比对升级前后INFORMATION_SCHEMA列定义如有超出白名单的变化则判定失败并自动生成候选白名单文件路径。3. 两种升级模式的完整流程3.1 冷升级默认不加-r冷升级的核心思路是“先停机、再替换、后验证”流程见 README.mdPhase 1 启动基准版本集群3 节点 Phase 2 创建测试资源DB / 超级表 / Topic / 索引 / TSMA / RSMA / Stream / 用户权限 Phase 3 写入初始数据 Phase 4 停止集群 → 逐节点替换二进制 → 重启集群目标版本 Phase 5 启动后台写入 / 查询 / 订阅负载 Phase 6 验证资源完整性 负载指标一个值得注意的工程细节冷升级的 Phase 4-5 会在新的子进程中运行使用目标版本的libtaos.so。原因是 glibc 在进程启动时只读取一次LD_LIBRARY_PATH运行中无法切换动态库版本冷升级完成后主进程必须以to_dir的库路径重新 spawn 一个子进程通过_TAOS_COLD_PHASE2环境变量标记确保连接器版本与升级后的服务器版本匹配。该逻辑实现在 run/main.py 的_spawn_cold_phase2与_run_cold_phase2而库路径的准备由 config_lib.py 的prepare_native_lib完成——它通过设置LD_LIBRARY_PATH并os.execv()重新拉起进程从进程启动那一刻就带上正确的库搜索路径。3.2 滚动升级-r/--rollupdate滚动升级强调“负载不停、逐节点替换”Phase 1 启动基准版本集群3 节点 Phase 2 创建测试资源 Phase 3 写入初始数据 Phase 4 启动后台写入 / 查询 / 订阅负载 逐节点滚动升级停止 → 替换 → 重启 → 等待 ready Phase 5 升级完成后继续观察 30 秒或 --quick 模式下 30 秒 Phase 6 验证资源完整性 负载指标滚动升级期间三个后台 Workerwriter.py、querier.py、subscriber.py持续运行Writer每秒向子表d0插入 1 行时间戳、电流、电压、相位写入前会等待订阅者确认订阅已建立subscribe_ready标志避免出现“先写入、后订阅”造成的起始空洞。Querier每秒执行一次SELECT COUNT(*) FROM {db}.{stable}统计查询延时。Subscriber使用taos.tmq.Consumer订阅 Topic记录相邻两批消息的时间间隔gap与累计消费行数。三个 Worker 均采用“失败不退出、持续重试”的策略连续失败达到MAX_CONSECUTIVE_RETRIES次或单次重试窗口超过RETRY_MAX_DURATION_S秒才计为 1 次真正失败*_error_count1。这样既能容忍升级瞬间的短暂连接中断又能通过失败计数暴露真实的持续性故障。4. 检查项逐项拆解4.1 升级过程本身无论哪种模式都要求所有节点均完成版本替换。实现上run/main.py 在升级完成后会打印检查项Rolling upgrade completed/Cold upgrade completed其真值来自 server/rollingUpgrade.py 中RollingUpgrader.run/ColdUpgrader.run的返回值。目标版本号并非取自安装目录名而是通过执行to_dir/taosd -V解析taosd version: X.Y.Z.W得到见_taosd_binary_version避免目录名与二进制实际版本漂移造成误判。4.2 升级期间持续写入 / 查询 / 订阅仅滚动升级滚动升级模式下Phase 4 期间这三个 Worker 全程运行并统计write_phase4_success、query_phase4_success、subscribe_phase4_recv三个阶段计数。升级结束后run/main.py 会打印滚动升级期间的运行概况成功写入行数、查询成功次数、订阅消费行数、重试总数用于人工观察节点切换瞬间是否存在明显中断。冷升级期间集群停机这三项不做验证表中为“—”。4.3 升级后写入 / 查询无失败批次升级完成后进入验证窗口默认 30 秒见VERIFY_DURATION_S工具持续采样三路 Worker 的write_last_latency、query_last_latency、subscribe_last_gap。判定规则来自_collect_resultsWrite: no failure batcheswrite_error_count 0为通过同时报告total_rows成功写入行数、retries重试次数与max_latency。Query: no failure batchesquery_error_count 0为通过报告max_latency。写入/查询延时上限在 config.py 中由MAX_WRITE_LATENCY_S默认 2.0 秒与MAX_QUERY_LATENCY_S默认 2.0 秒定义。注意 Worker 侧并不会因延时超限自杀退出最终 pass/fail 由 Phase 5 结束时统一判定。4.4 升级后订阅无长时间中断订阅者每次收到消息都会更新subscribe_last_recv_time。检查项Subscribe: data received within {N}s计算“当前时间 − 最近一次收到数据的时间”作为静默时长silence超过SUBSCRIBE_NO_DATA_TIMEOUT_S默认180 秒即判定失败——这与 check.md 中“默认超时 180 秒”的备注一一对应。同时报告的total_recv是累计消费行数。4.5 订阅消费行数 写入行数这是数据完整性的核心判据。实现上有两个精心设计的细节Writer 优雅停止Phase 5 结束时先通过独立的writer_stop_evt让 Writer 完成当前 INSERT 并更新write_total_rows后再退出而不是直接terminate()——否则会出现“行已提交到库并被 TMQ 消费但write_total_rows未自增”造成 received written 的假失败见 run/main.py 相关注释。Drain 等待Writer 停止后工具最多等待SUBSCRIBE_DRAIN_WAIT_S默认 60 秒让订阅者追平期间每秒打印written、subscribed与gap最终检查项Subscribe: rows received rows written要求write_total_rows subscribe_recv_total。4.6 test_user 认证与权限集合不变config.py 预置了一个受限权限的测试用户TEST_USER_NAME test_user TEST_USER_PASS Test1234 TEST_USER_READ_STABLE meters_ro # test_user 仅有 SELECT TEST_USER_WRITE_STABLE meters_wo # test_user 仅有 INSERT TEST_USER_HIDDEN_STABLE meters_hidden # test_user 无任何访问权限Phase 2 在基准版本上创建该用户并记录权限快照priv_before升级后由 resource/userVerifier.py 执行两项检查test_user authentication after upgrade用该账号重新认证是否成功。test_user privileges unchanged将升级后的权限集合与基准快照比对要求完全一致。值得注意若认证/校验报错中包含0x0141/Invalid signature、0x0140/Edition not compatible等特征码工具会解析出引擎侧错误码并以[0x0141] Invalid signature的形式报告见 run/main.py 的_is_sig_error与_engine_error_detail而不是笼统地显示“校验失败”。这是企业版授权与版本匹配问题的快速定位入口。4.7 Tag Index 保持存在Tag Index 是 TDengine 针对标签列的索引。工具在基准版本上对超级表meters的第二个标签列location创建显式索引idx_compat_location第一个标签列groupid由系统自动生成索引故不重复创建升级后验证该索引仍然存在Tag indexes preserved after upgrade。若不需要该检查可用--no-index跳过。4.8 TSMA / RSMA / Stream 保持按基准版本能力开关这三类检查并非在所有版本对上都执行而是由基准版本能力决定对应 check.md 中“仅基准版本 ≥ 3.3.6.0 / 3.3.7.0 / 3.3.8.0 时执行”的备注检查项基准版本要求检查内容跳过参数TSMA 保持存在≥ 3.3.6.0时序聚合对象tsma_compat_meterssum/avg/min/max/count/last升级后仍存在--no-tsmaStream 保持运行≥ 3.3.7.0新式流stream_compat_metersPERIOD 聚合升级后仍处于运行状态--no-streamRSMA 保持存在≥ 3.3.8.0结果集聚合rsma_compat_metersmin voltage / avg current / last phase升级后仍存在--no-rsma版本比较通过 run/main.py 的_version_ge完成——它从目录名如TDengine-enterprise-3.3.8.0中提取X.Y.Z.W四点版本号并做逐段比较若目录名无法解析则回退到X.Y.Z形式补(0,)。当基准版本不支持对应能力时工具会打印TSMA skipped: base version ... 3.3.6.0之类的提示并跳过而不是报错。4.9 INFORMATION_SCHEMA 无意外变化可选-S见下一节详解。5. INFORMATION_SCHEMA 检查与白名单机制5.1 开启检查两种升级模式均支持加-S/--check-sysinfo启用系统表 Schema 比对# 滚动升级 系统表检查 python -m run.main -F /opt/td/3.3.8.0 -T /opt/td/3.4.0.8 -r -S # 冷升级 系统表检查 python -m run.main -F /opt/td/3.3.8.0 -T /opt/td/3.4.0.8 -S开启后工具会在升级前后各拍一次INFORMATION_SCHEMA快照由 resource/sysinfo_checker.py 的snapshot实现再由compare_snapshots比对以下四类变化新增表 / 删除表added_tables/deleted_tables修改表新增列added_columns、删除列deleted_columns、列类型变化changed_type、列位置变化changed_position任何未在白名单中的变化都会使检查项INFORMATION_SCHEMA: no unexpected changes判定为[FAILED]并在 SUMMARY 中打印差异详情及候选白名单文件路径。5.2 生成白名单首次测试新版本对时遇到新的版本对时先用-G/--gen-whitelist生成候选白名单只做 schema 比对、不执行升级负载审核后再正式测试# 1. 生成白名单不执行负载测试 python -m run.main -F /opt/td/3.3.8.0 -T /opt/td/3.4.0.8 -G # 2. 审核生成的 whitelist/3.3.8.0~3.4.0.8.yaml # 3. 正式运行带检查的升级测试 python -m run.main -F /opt/td/3.3.8.0 -T /opt/td/3.4.0.8 -r -S⚠️-G与-S互斥不可同时使用-G模式只做 schema 比对后写文件退出不执行升级负载测试。-G也可指定输出路径python -m run.main -F from -T to --gen-whitelist /tmp/my_wl.yaml相对路径会写入白名单目录下绝对路径按原样写入见 whitelist_loader.py 的gen_whitelist_filepath。失败时的自动提示若-S检查发现意外变化工具会在当前工作目录自动生成一个候选白名单文件并在 SUMMARY 中打印其绝对路径方便直接复制使用INFORMATION_SCHEMA: no unexpected changes .............. [FAILED] added : INS_DATABASES.allow_drop ~ pos : INS_XNODE_AGENTS.update_time pos 4 - 5 /root/.../hot_update/3.3.8.0~3.4.0.8.yaml5.3 白名单文件格式与版本前缀匹配白名单文件存放在whitelist/目录可用--whitelist-dir DIR指定其他目录文件名格式为{from_prefix}~{to_prefix}.yaml支持版本前缀匹配——前缀越短覆盖范围越广文件名匹配范围3~3.yaml所有 3.x.x.x → 3.x.x.x 升级3.3~3.4.yaml所有 3.3.x.x → 3.4.x.x 升级3.3.6~3.4.yaml3.3.6.x → 3.4.x.x 升级3.3.6.0~3.4.0.8.yaml仅精确版本对 3.3.6.0 → 3.4.0.8当一个升级路径命中多个白名单文件时所有匹配文件取并集每个文件中允许的变化项都会被放行见 whitelist_loader.py 的load_whitelists。YAML 文件支持四类变更声明对应apply_whitelist中的过滤逻辑# 升级路径注释自动生成时填写 # from_version : 3.3.8.0 # to_version : 3.4.0.8 # 新增的整张表白名单内 预期内不报错 added_tables: - INS_NEW_TABLE # 删除的整张表 deleted_tables: [] # 修改了列定义的表 modified_tables: - table: INS_DATABASES # 新增列 added_columns: - allow_drop # 删除列 deleted_columns: [] # 列类型变化写列名即可任何类型变化都被允许 changed_type: - config # 列位置变化写列名即可 changed_position: - update_time仓库中已有一份真实的示例白名单 whitelist/3.4~3.4.yaml覆盖 3.4.0.x → 3.4.x 的升级路径。它展示了更复杂的写法例如INS_XNODE_AGENTS同时包含added_columnstoken、status、deleted_columnsscope与changed_positioncreate_time 从第 3 列移到第 4 列INS_STREAMS.sql从VARCHAR(2048)变为VARCHAR(49152)等——这些都可作为编写白名单的参考模板。6. 环境要求与命令行参数6.1 环境要求操作系统Linuxx86_64Python3.8依赖pyyamlpip install pyyamlTDengine Python 连接器taospypip install taospy单台测试机工具在同一台机器上通过不同端口启动多个 taosd 进程dnode16030dnode26130dnode36230无需多台机器安装包两个已解压的 TDengine 安装目录各自包含taosd与libtaos.so/opt/tdengine/ ├── 3.3.8.0/ │ ├── taosd │ └── libtaos.so └── 3.4.0.8/ ├── taosd └── libtaos.so6.2 命令行参数入口命令python -m run.main -F 基准版本目录 -T 目标版本目录 [选项]在 test/tools/compat-check 目录下执行。参数简写是否必填默认值说明--from-dir DIR-F必填—基准版本目录含taosd和libtaos.so--to-dir DIR-T必填—目标版本目录--path DIR-p可选~/td_rolling_upgrade集群数据和配置文件的工作目录--fqdn HOST-f可选socket.gethostname()测试机的 FQDN--rollupdate-r可选关闭冷升级开启滚动升级模式--quick-q可选关闭快速模式100 子表 × 1000 行30 秒验证窗口--check-sysinfo-S可选关闭升级后对比INFORMATION_SCHEMA列定义变化--gen-whitelist [FILE]-G可选—生成白名单文件后退出不执行负载测试与-S互斥--whitelist-dir DIR—可选脚本根目录/whitelist白名单文件目录--no-rsma—可选关闭跳过 RSMA 创建与验证--no-tsma—可选关闭跳过 TSMA 创建与验证--no-stream—可选关闭跳过 Stream 创建与验证--no-user—可选关闭跳过 test_user 权限创建与验证--no-index—可选关闭跳过 Tag Index 创建与验证--help-h——打印帮助信息后退出6.3 快速开始示例cd test/tools/compat-check # 冷升级默认 python -m run.main -F /opt/td/3.3.8.0 -T /opt/td/3.4.0.8 # 滚动升级热升级 python -m run.main -F /opt/td/3.3.8.0 -T /opt/td/3.4.0.8 -r # 快速模式CI 冒烟测试 python -m run.main -F /opt/td/3.3.8.0 -T /opt/td/3.4.0.8 -r -q # 带 INFORMATION_SCHEMA 检查 python -m run.main -F /opt/td/3.3.8.0 -T /opt/td/3.4.0.8 -r -S7. 配置参数config.pyconfig.py 集中管理集群规模、数据集大小与运行时阈值修改后无需改动命令行。主要参数如下参数默认值说明DNODE_COUNT3集群节点数MNODE_COUNT3MNode 数量REPLICA3数据库副本数BASE_PORT6030dnode1 端口dnode26130dnode36230SUBTABLE_COUNT100子表数量INIT_ROWS_PER_SUBTABLE10000每子表初始行数确保 WAL / data / stt 均有文件WRITE_BATCH_SIZE5000每次 INSERT 批量行数WRITE_THREADS20初始化阶段并发写入线程数VERIFY_DURATION_S30升级后观察窗口秒MAX_WRITE_LATENCY_S2.0写入延时上限秒MAX_QUERY_LATENCY_S2.0查询延时上限秒MAX_SUBSCRIBE_GAP_S2.0订阅消息间隔上限秒RETRY_INTERVAL_S1每次重试间隔秒MAX_CONSECUTIVE_RETRIES30连续失败超过此次数计为 1 次真正失败RETRY_MAX_DURATION_S150单次 SQL 重试超过此秒数也计为 1 次失败SUBSCRIBE_NO_DATA_TIMEOUT_S180订阅超过此秒数未收到数据判定不通过SUBSCRIBE_DRAIN_WAIT_S60Phase 5 结束前等待订阅追上写入的最大时间NODE_INSTALL_SLEEP_S20节点停止后模拟安装耗时的等待时间秒NODE_READY_TIMEOUT_S180等待单节点 ready 的最大时间秒GRACEFUL_STOP_TIMEOUT30taosd SIGTERM 后等待退出的最大时间快速模式-q会将以下三项覆盖为小值用于冒烟测试参数quick 模式值SUBTABLE_COUNT100INIT_ROWS_PER_SUBTABLE1000VERIFY_DURATION_S30资源对象名称DB、超级表、Topic、用户、索引、TSMA/RSMA/Stream 等也在 config.py 中统一定义如DB_NAMEtest_db、STABLE_NAMEmeters、TOPIC_NAMEtest_topic、TSMA_NAMEtsma_compat_meters、RSMA_NAMErsma_compat_meters、STREAM_NAMEstream_compat_meters。8. 输出格式、结果解读与退出码8.1 三层输出工具输出分为三层见 docs/User Manual.md步骤日志[HH:MM:SS]前缀每个 Phase 的进度信息内联错误[internal-error]前缀内部模块错误输出到 stderrSUMMARY 框测试结束后统一打印所有检查结果。测试开始时先打印运行概要════════════════════════════════════════════════════════════════════════ TDengine Rolling Upgrade Test ──────────────────────────────────────────────────────────────────────── From version : 3.3.8.0 To version : 3.4.0.8 Host (FQDN) : myhost Cluster : 3 DNODEs / 3 MNODEs / 3-replica Dataset : 100 subtables × 10,000 rows Verify window: 30s ════════════════════════════════════════════════════════════════════════结束时打印 SUMMARY 框逐条列出检查结果与关键指标════════════════════════════════════════════════════════════════════════ TDengine Rolling Upgrade Test ─ SUMMARY 3.3.8.0 ──▶ 3.4.0.8 │ host: myserver │ 3 dnodes / 3 mnodes ════════════════════════════════════════════════════════════════════════ Rolling upgrade completed ............................ [passed] Write: no failure batches ............................ [passed] failures0 total_rows1,234 retries2 max_latency0.312s Query: no failure batches ............................ [passed] failures0 max_latency0.108s Subscribe: data received within 180s ................. [passed] silence1.2s total_recv1,234 Subscribe: rows received rows written ............. [passed] written1,234 received1,234 diff0 test_user authentication after upgrade ............... [passed] test_user privileges unchanged ...................... [passed] Tag indexes preserved after upgrade .................. [passed] TSMA preserved after upgrade ......................... [passed] RSMA preserved after upgrade ......................... [passed] Stream preserved after upgrade ....................... [passed] INFORMATION_SCHEMA: no unexpected changes ............ [passed] (all changes whitelisted) ──────────────────────────────────────────────────────────────────────── Result : PASS ✓ Duration: 4m 32s Write : max_latency0.312s Query: max_latency0.108s Subscribe: max_gap0.950s ════════════════════════════════════════════════════════════════════════8.2 退出码退出码含义0全部检查通过1至少一项检查失败或发生错误2参数错误缺少必填参数如未提供-F/-T失败时SUMMARY 中会打印日志目录路径path/dnode*/log以便排查。9. 典型使用场景场景 A新版本发布前的完整 CI 验证# 1. 首次测试该版本对时先生成白名单 python3 -m run.main -F /pkg/3.3.8.0 -T /pkg/3.4.0.8 --gen-whitelist # 2. 审核 whitelist/3.3.8.0~3.4.0.8.yaml 后正式运行 python3 -m run.main -F /pkg/3.3.8.0 -T /pkg/3.4.0.8 --rollupdate --check-sysinfo场景 B小版本补丁回归快速python3 -m run.main \ -F /pkg/3.4.0.0 \ -T /pkg/3.4.0.8 \ --rollupdate --quick --check-sysinfo场景 C冷升级停机升级验证python3 -m run.main \ -F /pkg/3.3.8.0 \ -T /pkg/3.4.0.8 \ --check-sysinfo场景 D自定义白名单目录python3 -m run.main \ -F /pkg/3.3.8.0 \ -T /pkg/3.4.0.8 \ --rollupdate \ --check-sysinfo \ --whitelist-dir /ci/tdengine/whitelists10. 运行前清理与常见问题10.1 运行前清理每次运行前需确保上次的集群进程和数据已清理详见 README.mdpkill -9 taosd rm -rf ~/td_rolling_upgrade # 或 --path 指定的目录10.2 常见问题Q: 报错ModuleNotFoundError: No module named taosA: 安装 TDengine Python 连接器pip install taospy同时确保pyyaml已安装。Q:--check-sysinfo失败不知道如何编写白名单A: 按 SUMMARY 中打印的候选白名单路径找到自动生成的文件审核后将允许项并入whitelist/目录下对应版本对的 YAML 文件即可也可先用-G生成候选白名单再审核。Q:-G和-S可以同时使用吗A: 不可以两者互斥。-G只做 schema 比对后写文件退出不执行升级负载测试。Q: 白名单文件名版本前缀写多短合适A: 建议先用精确四位版本号如3.3.8.0~3.4.0.8.yaml确认无误后若需覆盖整个大版本升级路径再改为3.3~3.4.yaml。Q: 多个白名单文件都匹配时怎么处理A: 所有匹配文件取并集每个文件中允许的变化项都会被放行。结语升级兼容性不是“能起来就行”而是要求写入、查询、订阅、权限、索引与各类聚合对象在版本切换后行为完全一致。check.md 给出的 15 项检查清单覆盖了从负载持续性、数据完整性到系统表 Schema 的全部关键维度而 compat-check 工具把这份清单落成了可重复执行的自动化流水线。理解每条检查项的判定逻辑失败计数阈值、180 秒订阅静默上限、行数对账、白名单并集规则与底层实现LD_LIBRARY_PATH重执行、Worker 优雅停止、版本能力开关能帮助你在自己的升级 CI 中精准配置阈值、快速定位失败原因让每次升级都有据可查、风险可控。【免费下载链接】TDengineHigh-performance, scalable time-series database designed for Industrial IoT (IIoT) scenarios项目地址: https://gitcode.com/GitHub_Trending/tde/TDengine创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考