ClickHouse v24.2.2.71-stable 版本解析:补丁内容、安全修复与源码级实现解读
【免费下载链接】ClickHouseClickHouse® is a real-time analytics database management system项目地址: https://gitcode.com/GitHub_Trending/cli/ClickHouse
v24.2.2.71-stable 是 ClickHouse 在 2024 年 2 月发布的第二个 stable 补丁版本,基于 v24.2.1.2248-stable 修复了十余处用户可见的缺陷,涵盖并行查询执行、分析器、并行解析、KQL 复合操作符、S3 集成、数组/聚合函数以及 Keeper 等多个核心模块,并包含一处针对 HTTP 解压流程的缓冲区溢出安全修复。阅读本文后,你将系统掌握该补丁版本的全部变更明细、每条修复对应的底层源码位置与触发场景,以及升级到该版本时的关注要点。
版本概览与基线对比
本变更记录来自 docs/changelogs/archive/v24.2.2.71-stable.md,核心信息如下:
- 发布版本:
v24.2.2.71-stable,提交哈希9293d361e72 - 对比基线:
v24.2.1.2248-stable,提交哈希891689a4150 - 变更构成:
- 1 项Improvement(改进)
- 14 项Bug Fix(用户可见的官方稳定版行为修复)
- 11 项CI Fix or Improvement(CI 修复或改进,无需 changelog 条目)
- 4 项NOT FOR CHANGELOG / INSIGNIFICANT(不进入 changelog 的杂项)
从整体构成看,该补丁版本没有引入新功能,全部精力集中在稳定化与安全性上,符合 stable 分支“低风险、高收敛”的发布策略。当前仓库的版本演化仍在继续,最新版本信息可参考 cmake/autogenerated_versions.txt。
Improvement:时区数据库升级到 2024a
本版本唯一一项功能性改进是:
- 更新 tzdata 至 2024a(PR #60768,作者 Raúl Marín)
tzdata 的升级直接关系到所有与时区相关的行为:toTimezone/fromUnixTimestamp等时区换算函数、DateTime/DateTime64类型的显示与排序、now()的时区语义,以及timezone系统表的内容。2024a 版 tzdata 主要反映了世界各国(尤其是中东地区)对夏令时规则的调整。对于依赖精确时间语义的查询(如广告归因、日志时间分桶),升级后同一 UTC 时间在不同时区的本地化表示可能发生变化,建议在升级时对涉及时区转换的报表做一次回归校验。
Bug Fix 全清单与源码级解析
并行执行与查询优化
1.FINAL并行优化在罕见场景下产生错误结果
在并行优化启用时,带FINAL的查询(即对ReplacingMergeTree、AggregatingMergeTree等表强制合并相同排序键行的操作)可能在罕见情况下返回错误结果。修复 PR #60041 修正了并行FINAL的合并逻辑。触发面较窄,但后果严重——错误结果通常难以通过常规测试察觉,属于典型的“沉默型”数据正确性问题。使用parallel_view_processing相关设置的 MergeTree 重度用户应关注此修复。
2. 避免CREATE TABLE时计算标量子查询
此前CREATE TABLE语句中的标量子查询(scalar subquery)会被提前计算,导致在特定场景(issue #59795、#59930)下行为异常或报错。修复 PR #60464 是对此前 PR #57855 的重新实现,其思路是:CREATE TABLE的列定义解析只关心类型与默认表达式结构,无需在 DDL 阶段求值标量子查询。
3.allow_experimental_analyzer在子查询中被动态修改导致崩溃
当查询在子查询作用域内变更allow_experimental_analyzer设置值时,可能触发崩溃。修复 PR #60770 保证了分析器(Analyzer)开关在子查询中的一致性。这提示:全局设置项在子查询内部被临时改写属于高风险操作,该修复堵住了这一崩溃路径。
并行解析与死锁
4. 并行解析在大量行因错误被跳过时发生死锁
并行解析(parallel parsing)模式下,当输入数据中大量行因格式错误被跳过时,解析线程之间可能互相等待,形成死锁。修复 PR #60516 所依赖的解析基础设施中,错误行跳过与线程同步的状态机在极端输入下需要正确处理“无可用工作”的信号。
KQL 复合操作符与查询大小
5. KQL 复合操作符(如mv-expand)不再受max_query_size误限
KQL(Kusto Query Language)复合操作符在展开时会生成超长查询文本,此前被max_query_size设置错误地截断(关联 issue #59626)。修复 PR #60534 目录。
系统表与类型提示
6. 减少system.numbers的读取行数
system.numbers是 ClickHouse 生成序列的常用工具表,此前在某些查询计划下会读取超出必要数量的行(issue #59418)。修复 PR #60546 优化了读取行数,直接减少不必要的 I/O 与 CPU 开销,提升依赖该表的测试与基准查询效率。
7. 日期类型不再输出数字提示
此前对日期类型的错误提示中会附带“数字”类建议(如建议使用toDate还是直接传数字),此类提示对日期语义易产生误导。修复 PR #60577 移除了日期类型的数字提示,使报错信息更准确。
安全修复
本版本包含两项由外部研究团队与 Fuzzer 发现并上报的安全相关问题,建议优先评估升级:
8. HTTP 解压流程缓冲区溢出(安全)
- 攻击者可通过构造“编解码器组合 + 触发数值溢出的尺寸”的请求,让 HTTP 服务器在解压数据时发生缓冲区溢出;
- 编解码器
NONE在错误的输入数据上也可能触发缓冲区溢出。
该问题由 TIANGONG 研究团队通过官方 Bug Bounty 项目(issue #38986)提交,修复 PR #60731 目录,其中NONE编解码器即CompressionCodecNone(见 src/Compression/CompressionCodecNone.h)。凡对外暴露 HTTP 接口(尤其是http_port与https_port)的部署,都强烈建议升级到本版本或更高版本。
9. SQL/JSON 函数读取未初始化内存(安全)
SQL/JSON 相关函数(如JSON_EXISTS、JSON_VALUE、JSON_QUERY等)在特定输入下能够读取未初始化内存,由 Fuzzer 发现(issue #60017),修复 PR #60738。SQL/JSON 函数族实现在 src/Functions/JSON 目录。读取未初始化内存属于未定义行为,可能泄露敏感数据或被用于拒绝服务,同样建议尽快升级。
S3 集成
10. 不再在UploadPart与CompleteMultipartUpload调用中设置x-amz-meta-*自定义元数据头
此前分片上传(multipart upload)会在UploadPart与CompleteMultipartUpload请求中错误携带x-amz-meta-*自定义元数据头,部分对象存储服务会拒绝这类请求或产生意外行为。修复 PR #60748 将自定义元数据设置限制在正确的初始化请求(CreateMultipartUpload)阶段。S3 表函数与 S3 磁盘相关代码见 src/Storages/S3 与 src/Disks/S3。
11. 从 S3 读取时跳过过多 key 导致段错误(segfault)
当从 S3 列表结果中跳过过多不匹配的 key 时,可能触发段错误。修复 PR #60849 为列表迭代器增加了边界保护。该问题常见于 S3 表上带glob通配符或前缀过滤的查询,前缀不匹配数量极大时容易复现。
数组与聚合函数
12.arrayEnumerateRanked崩溃修复
arrayEnumerateRanked(及其家族arrayEnumerateUniqRanked、arrayEnumerateDenseRanked)在特定输入下崩溃,修复 PR #60764 解决了该问题。
从源码看,这是一个为 Metrica 网络分析系统定制的高维数组计数函数族(见 src/Functions/array/arrayEnumerateRanked.h 头部注释)。其核心语义是:在指定深度(depth)下对多维数组中的不同值进行编号计数,支持clear_depth参数重置计数器:
-- 一维:返回每个元素第几次出现 SELECT arrayEnumerateUniqRanked(['hello', 'world', 'hello']) -- [1, 1, 2] -- 二维数组,默认看最大深度 SELECT arrayEnumerateUniqRanked([['hello', 'world'], ['hello'], ['hello']]) -- [[1,1],[2],[3]] -- 指定 clear_depth=1,顶层元素各自重新计数 SELECT arrayEnumerateUniqRanked(1, [['hello', 'world'], ['hello'], ['world'], ['world']]) -- [[1,1],[2],[2],[3]]多个数组参数会按 zip 成元组的方式共同参与编号(['hello', 'hello', 'world', 'world'], ['a', 'b', 'b', 'b']→[1, 1, 1, 2]),深度不同的数组会被提升(提升方式为复制元素)到统一结构。参数解析与深度推断逻辑位于 src/Functions/array/arrayEnumerateRanked.cpp 的getArraysDepths函数中:clear_depth必须是Const(UInt64)且为正整数,返回值类型是最大有效深度对应的Array(UInt32)嵌套类型。该崩溃修复保证了此类多维输入的稳定性。
13.groupArraySorted多个缺陷修复
groupArraySorted聚合函数存在多个缺陷,修复 PR #61203 一并解决。
groupArraySorted实现于 src/AggregateFunctions/AggregateFunctionGroupArraySorted.cpp,用于在分组内收集按值排序后的数组,并可通过可选的limit参数限制返回元素个数(与groupArray的max_array_size语义类似,但顺序确定)。从源码看,其实现提供两种内部策略:
- heap 策略(
GroupArraySortedDataHeap):维护一个最小堆,超过limit时用heapReplaceTop替换堆顶并调整,保证任意时刻只保留最小的limit个元素,内存占用有界; - sort 策略(
GroupArraySortedDataSort):先追加再按需排序,通过partialSortAndLimitIfNeeded用nth_element定期截断,最终在sortAndLimit中完成排序(数值类型优先trySort,失败则回退到 LSD 基数排序RadixSort)。
limit参数在构造时被校验,上限为aggregate_function_group_array_sorted_max_element_size = 0xFFFFFF,超限直接抛BAD_ARGUMENTS(见 src/AggregateFunctions/AggregateFunctionGroupArraySorted.cpp)。本次修复覆盖了该聚合在边界输入下的崩溃与错误结果问题。
Keeper
14. Keeper 独立二进制(standalone binary)的运行时重配置修复
ClickHouse Keeper 以独立二进制运行时,动态重配置(runtime reconfig,即通过SYSTEM RELOAD CONFIG或 4lw 命令在线调整配置)存在缺陷,修复 PR #61233 与 programs/keeper。
CI 修复与杂项变更
本版本还包含 11 项 CI 修复与改进(changelog 条目非必需)及 4 项不进入 changelog 的杂项,主要包括:
- CI 流程重构:将工作流 yml 文件抽象化(PR #60421)、docker server 任务无需输入参数即可清理 yml 文件(PR #60602)、
build_report任务仅由ci_config定义(PR #60613)、为合并队列(merge queue)支持做准备(PR #61099)等; - 发布与回退流程:调试并修复
markreleaseready(PR #60611)、发布分支上不再等待 CI pending 任务以适配 GitHub 任务超时(PR #60652)、回退(backport)中为 "special build check" 报告设置构建数量上限(PR #60850); - 执行器健壮性:在
spawnThreads抛出异常时正确取消PipelineExecutor(PR #60499),涉及 src/Processors/Executors/PipelineExecutor.cpp 中的线程启动与异常清理路径; - 函数代码卫生:为
seriesOutliersDetectTukey增加通用健壮性检查(PR #60535)。该函数基于 Tukey Fences 方法检测时间序列异常点,实现在 src/Functions/seriesOutliersDetectTukey.cpp,接受 1 个(time_series数组)或 4 个参数(数组 +min_percentile+max_percentile+k),默认分位数为 25%/75%、k=1.5,分位数合法区间为[0.02, 0.98],k必须为非负数(见 src/Functions/seriesOutliersDetectTukey.cpp):-- 使用默认参数检测异常点 SELECT seriesOutliersDetectTukey([1, 2, 3, 100, 4, 5]); -- 自定义分位数与 k 值 SELECT seriesOutliersDetectTukey([1, 2, 3, 100, 4, 5], 0.2, 0.8, 2.0);
升级建议与验证要点
综合本版本变更,升级到v24.2.2.71-stable时建议重点关注以下方面:
- 安全性优先:HTTP 解压缓冲区溢出(PR #60731)与 SQL/JSON 未初始化内存读取(PR #60738)均为攻击者可触达的缺陷,所有对外暴露 HTTP(S) 端口的实例应尽快升级;
- S3 用户:若使用 S3 表函数、S3 磁盘或分片上传,本次对
x-amz-meta-*头与列表跳过逻辑的修复(PR #60748、#60849)值得回归验证——尤其是带 glob/前缀过滤的大规模 S3 扫描; - Keeper 用户:独立二进制部署且依赖在线重配置的集群,应验证升级后的
SYSTEM RELOAD CONFIG行为(PR #61233); - 查询正确性:使用
FINAL并行优化、arrayEnumerateRanked系列函数、groupArraySorted聚合的查询,建议在升级后对照已知结果做回归比对(对应 PR #60041、#60764、#61203); - 时区行为:tzdata 2024a 生效后,涉及时区转换的报表结果可能与旧版本存在差异,需按业务场景复核。
总而言之,v24.2.2.71-stable是一个典型的“稳定性 + 安全”收敛补丁:没有新特性,但对并行执行、解析器、S3、Keeper 及多项数组/聚合函数的边界场景做了系统性修补,是 v24.2 系列值得采纳的推荐版本。
【免费下载链接】ClickHouseClickHouse® is a real-time analytics database management system项目地址: https://gitcode.com/GitHub_Trending/cli/ClickHouse
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考