ClickHouse v24.3.13.40-lts 发布解析:14 项稳定性修复背后的源码原理与实战验证
2026/9/16 12:47:46 网站建设 项目流程

ClickHouse v24.3.13.40-lts 发布解析:14 项稳定性修复背后的源码原理与实战验证

【免费下载链接】ClickHouseClickHouse® is a real-time analytics database management system项目地址: https://gitcode.com/GitHub_Trending/cli/ClickHouse

导读:本文基于 ClickHouse 仓库中的官方发布说明 docs/changelogs/archive/v24.3.13.40-lts.md,完整解析 v24.3.13.40-lts 这一 LTS 补丁版本包含的 14 项用户可见 Bug 修复与 4 项内部改进。你将了解每项修复针对的具体故障场景、对应源码模块与底层原因,以及如何在生产环境验证这些修复是否生效,为升级评估提供依据。

版本背景:一次标准的 LTS 补丁迭代

v24.3.13.40-lts 属于 ClickHouse 24.3 长期支持(LTS)分支的补丁版本,其基线为v24.3.12.75-lts(commit 7cb5dff8019),本次发布基于7acabd77389提交。LTS 分支的特点是:不引入新功能,专注于修复用户在生产环境中可见的错误行为,因此该版本的变更清单几乎全部由Bug Fix (user-visible misbehavior in an official stable release)构成。

从变更结构看,v24.3.13.40-lts 的修复集中在以下几大领域:

领域修复数量代表问题
存储引擎与复制(MergeTree/Replicated)4相交数据分片、shadow 目录遍历、Replicated 数据库建表
查询执行与聚合函数5物化视图 INTERSECT 段错误、groupArraySorted 崩溃泄漏、负零逻辑错误
HTTP 服务与客户端2Content-Encoding 响应头缺失、异步插入输出处理
会话管理与生命周期3命名会话悬挂、数据分片析构 terminate、keeper 日志

存储引擎与复制:数据分片一致性的关键修复

重启后 Drop Range 产生的相交数据分片

Backported in [#63976]:Fix intersect parts when restart after drop range. [#63202]

这是本版本最核心的存储层修复之一。在 MergeTree 表引擎中,数据以不可变的 part(数据分片)为单位存储,每次DROP RANGE(按分区键范围删除数据)会生成新的 part。当节点在删除过程中重启时,可能出现两个相互覆盖(相交)的 part 同时存在的中间状态,导致查询读到重复或错误数据。

从源码看,相交 part 的检测与处理逻辑贯穿整个 MergeTree 代码路径:

  • src/Storages/MergeTree/ActiveDataPartSet.cpp 维护 active part 集合,负责判断 part 之间的覆盖(containment)与相交(intersection)关系;
  • src/Storages/MergeTree/MergeTreeData.cpp 中的加载逻辑会检查"incoming part 与已有 part 相交"的场景,并区分事务已提交(committed)与已回滚(RolledBack)两种状态——对于来自已回滚事务的 part 直接跳过,只有当事务元数据无法读取(RollbackStatus::Unreadable)时才会抛出CORRUPTED_DATA错误提示磁盘损坏或写入不完整;
  • src/Storages/MergeTree/MergeFromLogEntryTask.cpp 在复制队列执行 merge 任务时,会断言"两个相交 part 同时覆盖源 part"属于逻辑错误,并输出"Part {} is covered by {} but should be merged into {}"的诊断日志。

实战建议:升级后可通过system.parts检查是否存在相互覆盖的 active parts:

SELECT table, name, active, partition FROM system.parts WHERE database = 'default' AND active ORDER BY table, name;

若修复生效,重启后相交 part 会被正确收敛为覆盖关系或直接标记为 Outdated。

遍历 shadow 目录时忽略 frozen_metadata.txt

Backported in [#71146]:Ignore frozen_metadata.txt while traversing shadow directory from system.remote_data_paths. [#70590]

shadow目录是 ClickHouse 进行分区备份(ALTER TABLE ... FREEZE)时存放冻结数据快照的位置,其中可能包含frozen_metadata.txt这类非数据文件。修复前,system.remote_data_paths系统表在遍历远程存储上的 shadow 目录时可能误将元数据文件当作数据 part 处理,产生错误的路径清单。修复后遍历逻辑显式跳过该文件,使远程路径报告保持准确。

Replicated 数据库下基于表函数建表失败

Backported in [#70877]:Fix table creation withCREATE ... AS table_function()with databaseReplicatedand unavailable table function source on secondary replica. [#70511]

当使用Replicated数据库引擎且执行CREATE TABLE ... AS table_function()时,如果主副本(primary replica)上的表函数源暂不可用,次要副本(secondary replica)此前会建表失败。修复保证建表 DDL 在复制队列中正确传播,次要副本即使在源不可用时也能完成元数据创建,避免复制链路中断。

查询执行与聚合函数:崩溃与内存问题的根源

物化视图 + 两个 SELECT + INTERSECT 导致服务段错误

Backported in [#70619]:Fix server segfault on creating a materialized view with two selects and anINTERSECT, e.g.CREATE MATERIALIZED VIEW v0 AS (SELECT 1) INTERSECT (SELECT 1);. [#70264]

INTERSECT(交集)查询在解析阶段会为左右分支各生成一个子查询块。当物化视图的 SELECT 查询形如(SELECT 1) INTERSECT (SELECT 1)(即两个无表源的 SELECT)时,旧版本在视图元数据初始化过程中会因空块处理不当触发空指针解引用,直接导致 server 段错误崩溃。修复后即使查询没有实际数据源,也能安全完成物化视图创建。

验证方式(修复后的行为):

CREATE MATERIALIZED VIEW v0 AS (SELECT 1) INTERSECT (SELECT 1); -- 不再崩溃,正常返回 SELECT * FROM v0;

stateful window functions 在内存未对齐时创建失败

Backported in [#70682]:Fix creation of stateful window functions on misaligned memory. [#70631]

窗口函数在聚合过程中需要维护跨行状态(stateful state),这些状态对象在内存 arena 中分配时必须满足特定的对齐要求。旧实现未正确处理未对齐(misaligned)内存地址,在部分平台上创建有状态窗口函数时会触发未定义行为或崩溃。修复确保状态对象在正确的对齐边界上初始化。

AggregateFunctionGroupArraySorted 的崩溃与内存泄漏

Backported in [#71113]:Fix a crash and a leak in AggregateFunctionGroupArraySorted. [#70820]

这是聚合函数家族中一个相对较新的成员。源码位于 src/AggregateFunctions/AggregateFunctionGroupArraySorted.cpp,其语义为"返回升序排列的前 N 个元素",在 src/AggregateFunctions/registerAggregateFunctions.cpp 中注册。

从实现看,该函数根据N的大小选择两种策略(源码第 43-50 行):

  • 堆策略(heap):当N <= 1,000,000时,使用最大堆维护前 N 小元素,新元素若不小于堆顶则直接丢弃(addElement 实现);
  • 排序策略(sort):当N > 1,000,000时,先追加后分段排序截断,并在输出阶段调用trySort,失败时回退到基数排序(RadixSort,sortAndLimit 实现)。

本次修复针对的是堆/排序切换边界与内存扩容路径中的崩溃与泄漏:在合并(merge)多个分组状态、或结果数组超过max_elements上限进行 resize 时,旧代码存在释放不完整的问题。另外,构造参数N超过0xFFFFFF时会抛出BAD_ARGUMENTS异常(源码第 244-248 行),反序列化时数组大小超过上限则抛出TOO_LARGE_ARRAY_SIZE(源码第 313-314 行),修复保证这些异常路径不再伴随内存损坏。

验证示例

-- 正常用法(N ≤ 100 万走堆策略) SELECT groupArraySorted(10)(number) FROM numbers(100); -- ┌─groupArraySorted(10)(number)─┐ -- │ [0,1,2,3,4,5,6,7,8,9] │ -- └──────────────────────────────┘ -- 覆盖排序策略与大 N 场景,观察是否稳定返回 SELECT length(groupArraySorted(2000000)(number)) FROM numbers(5000000);

两级哈希表中负零导致的逻辑错误

Backported in [#70990]:Fix a logical error due to negative zeros in the two-level hash table. This closes [#70973]. [#70979]

浮点数存在+0.0-0.0两种表示,二者数值相等但位模式不同。ClickHouse 的两级哈希表(two-level hash table,用于并行聚合)在计算桶索引时,若未对-0.0做归一化处理,会出现"逻辑上相等的数据被散列到不同桶"的问题,最终表现为GROUP BY聚合结果错误或内部断言失败。修复统一了对负零的归一化处理,确保等值数据必然落入同一桶。

SortCursor 0 列时的崩溃(旧分析器)

Backported in [#71594]:Prevent crash in SortCursor with 0 columns (old analyzer). [#71494]

SortCursor是排序执行器的核心数据结构,负责在归并排序过程中跨数据块移动游标。在旧分析器(analyzer)路径下,当排序键列表为空(0 列)时,游标初始化会访问不存在的列偏移数组,触发崩溃。修复在游标构造时对 0 列场景做了防护,保证ORDER BY边界情况(如常量排序键)不再崩溃。

HTTP 服务与客户端:响应与插入的可靠性

部分压缩响应缺失 Content-Encoding 头

Backported in [#71482]:FixContent-Encodingnot sent in some compressed responses. [#64802]. [#68975]

HTTP 接口支持基于Accept-Encoding协商对响应体做压缩(gzip、deflate、br、zstd、lz4、snappy 等)。修复前,部分响应路径(尤其是流式写入场景)未在首包写入时设置Content-Encoding头,客户端会误把压缩字节流当作明文解析,导致响应内容损坏。

从源码看,压缩头的设置集中在两个位置:

  • src/Server/HTTP/HTTPResponseHelpers.h:统一的响应头辅助函数,先检查响应是否已设置Content-Encoding(避免重复压缩),再按协商结果设置对应编码名,其中snappy使用标准 framing 格式;
  • src/Server/HTTP/WriteBufferFromHTTPServerResponse.cpp:在 HTTP 响应缓冲区的首包数据写出时设置Content-Encoding头,对应的声明位于 src/Server/HTTP/WriteBufferFromHTTPServerResponse.h。

修复核心是确保Content-Encoding在"压缩开启但响应体尚未产生"的边界路径上也被正确设置。可用 curl 验证:

curl -sI -H "Accept-Encoding: gzip" 'http://localhost:8123/?query=SELECT+1' | grep -i content-encoding # 期望输出:Content-Encoding: gzip

异步插入等待模式下的输出处理

Backported in [#70571]:Ignore all output on async insert withwait_for_async_insert=1. Closes [#62644]. [#70530]

使用 HTTP 异步插入(async insert)时,若开启wait_for_async_insert=1(默认开启),客户端等待插入真正落盘后才收到响应。旧版本在该模式下可能错误地返回中间输出内容,与"异步插入不返回数据"的语义冲突。修复后wait_for_async_insert=1时忽略所有查询输出,与异步插入协议保持一致,避免客户端将插入响应误解析为查询结果。

会话管理与生命周期:资源释放与守护进程稳定性

命名会话(named sessions)悬挂无法关闭

Backported in [#71246]:Fixed named sessions not being closed and hanging on forever under certain circumstances. [#70998]

命名会话用于在 HTTP 客户端之间共享会话状态(如临时表、设置)。修复前,在特定时序下(如会话持有期间连接异常断开),命名会话的引用计数未能正确归零,导致会话永不关闭,持续占用服务器资源直至耗尽。修复确保会话生命周期管理与连接状态强绑定,异常路径下也能正确释放。

数据分片析构函数异常导致进程 terminate

Backported in [#71371]:Add try/catch to data parts destructors to avoid terminate. [#71364]

C++ 中析构函数抛出异常会直接触发std::terminate导致进程退出。数据分片(MergeTreeDataPart)析构时会执行清理工作(如释放文件描述符、删除临时文件),若在此过程中抛异常,整个服务器会非正常终止。修复为析构路径添加了 try/catch 保护,将清理异常降级为日志记录,保证进程持续可用。

Keeper 慢 poll 日志与配置日志收敛

Backported in [#70538]:Remove slow poll() logs in keeper. [#70508]

Keeper(ClickHouse 的协调服务)在负载正常时仍可能周期性产生slow poll()告警日志,造成噪音并掩盖真实问题。该修复移除了这部分非必要日志。同时([#70971])对配置相关的重复日志行数做了限制,降低高配环境下的日志量。

内部改进与其他修复(NOT FOR CHANGELOG)

除用户可见修复外,本版本还包含 4 项内部改进:

  • CHECK 查询中的文件缓存删除([#69256],backport [#71022]):开启事务时执行CHECK查询会触发文件缓存(file cache)的错误清理,修复保证CHECK不再误删缓存数据;
  • CI 集成测试([#70329]):为 backport PR 启用集成测试(Integration Tests),提升补丁版本的回归验证覆盖;
  • 数据分片析构 try/catch(见上文,同时归入内部项);
  • 配置日志限制([#70879])。

升级与验证建议

  1. 确认当前版本
clickhouse-server --version # 或查询运行中的服务器 SELECT version();
  1. 升级后重点回归

    • 对执行过DROP RANGE的表,检查system.parts是否仍有相交 active parts;
    • curl -I验证 HTTP 压缩响应头;
    • 对使用groupArraySorted的大 N 查询做稳定性压测,确认无崩溃、无内存增长;
    • 验证命名会话在连接异常断开后能从system.sessions中正常消失。
  2. 监控指标:升级后观察system.errorsLOGICAL_ERRORCORRUPTED_DATA等错误码计数是否归零,以及 Keeper 日志中slow poll是否消失。

总结

v24.3.13.40-lts 是一份典型的 LTS 补丁版本,14 项用户可见修复覆盖了从存储引擎数据分片一致性、聚合函数内存安全,到 HTTP 协议响应头和会话生命周期管理的关键链路。每一项修复都能在 src 目录的对应模块(src/Storages/MergeTree、src/AggregateFunctions、src/Server/HTTP)中找到源码级印证。对于运行 24.3 LTS 分支的生产集群,本版本值得尽快评估升级,以规避相交数据分片、物化视图段错误与聚合函数内存泄漏等风险。

【免费下载链接】ClickHouseClickHouse® is a real-time analytics database management system项目地址: https://gitcode.com/GitHub_Trending/cli/ClickHouse

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询