news 2026/9/13 14:50:29

ClickHouse v21.9.2.17-stable 版本更新全解析:funnel 严格模式修复、S3 大对象复制与 22 项稳定版 Bug 修复

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ClickHouse v21.9.2.17-stable 版本更新全解析:funnel 严格模式修复、S3 大对象复制与 22 项稳定版 Bug 修复

ClickHouse v21.9.2.17-stable 版本更新全解析:funnel 严格模式修复、S3 大对象复制与 22 项稳定版 Bug 修复

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

本篇技术指南基于 ClickHouse 官方变更日志 v21.9.2.17-stable 展开,逐条解读该稳定版本相对于 v21.9.1.8000-prestable 的全部变更:包括 3 项功能改进、8 项常规 Bug 修复、1 项构建/测试改进,以及面向稳定版用户的 22 项用户可见问题修复。读者读完可完整掌握该版本的修复脉络,并深入理解 windowFunnel 严格模式、PREWHERE 自动优化、S3 分片上传、clickhouse-keeper 会话管理等核心模块的底层实现原理。

版本背景:v21.9.2.17-stable 与 v21.9.1.8000-prestable

v21.9.2.17-stable 是 ClickHouse 21.9 系列在 2022 年发布的一个重要稳定版本,其变更基线(base)是 prestable 版本 v21.9.1.8000。所谓 "stable" 版本,意味着本次发布只包含从 prestable 分支精选出的改进与修复,不引入新功能,重点在于把经过验证的修复回移(backport)到稳定分支,确保生产环境的可靠性。

本版本共包含以下分类的变更:

分类条目数说明
Improvement(功能改进)3库字典符号链接、S3 大对象分片上传、Keeper 会话过期逻辑
Bug Fix(常规修复)8覆盖漏斗函数、会话存储、类型转换、分布式表等
Build/Testing/Packaging Improvement1CI 构建基础设施调整
Bug Fix (user-visible misbehaviour in official stable release)22官方稳定版中的用户可见问题修复
NOT FOR CHANGELOG / INSIGNIFICANT9内部小修复,不进入对外变更日志

功能改进(Improvement)

允许库字典(library dictionary)路径使用符号链接

本次改进允许在库字典的路径配置中使用符号链接(symlink)。字典是 ClickHouse 中常用的数据映射机制,其路径此前要求必须是真实文件路径,这在某些通过符号链接管理数据目录的部署环境下会造成不便。此次改动后,字典路径解析对符号链接更加宽容。

S3 大对象上传改用 Multipart Copy

对于大体积的 S3 对象,本次更新改用Multipart copy upload(分片复制上传)方式。此前 S3 上的大对象复制操作容易受到单次请求大小限制(单次 CopyObject 最大支持 5GB)或超时影响;改用分片上传后,大对象会被拆分成多个 part 并行复制,显著提升大对象跨桶复制、备份等场景的稳定性与吞吐。从仓库结构看,S3 相关存储与备份实现位于 src/Storages 与 src/Backups 目录中,其中 StorageS3 类负责与 S3 存储的底层交互。

修复 Keeper 中奇怪的会话过期逻辑

clickhouse-keeper(内置的 ZooKeeper 兼容协调服务,源码位于 src/Coordination)此前存在一处会话过期逻辑异常,可能导致会话被过早或错误地判定过期。该问题在 CI 的 stress test 中曾被观察到。此次修复(对应 PR #28519)调整了会话过期的判定时机,使 Keeper 的会话管理行为符合预期。

常规 Bug 修复(Bug Fix)

windowFunnel 严格模式修复

本版本修复了windowFunnel聚合函数在strict模式下的一个 Bug(修复 issue #27469)。windowFunnel用于在滑动时间窗口内统计漏斗转化路径,其核心实现在 src/AggregateFunctions/AggregateFunctionWindowFunnel.cpp。

从源码可以看出,该函数支持多种严格模式开关(见该文件中的定义):

  • strict_deduplication:同一事件去重,仅对不重复的值应用条件;
  • strict_order:不允许其他事件的插入干扰路径,例如在A->B->D->C序列中,遇到D即停止寻找A->B->C,此时最大事件层级为 2;
  • strict_increase:仅对时间戳严格递增的事件应用条件;
  • allow_reentry:允许重入/跳过未来的步骤。

源码注释还明确指出,windowFunnel最多支持 32 个事件(The max size of events is 32),且算法整体复杂度为 O(n·log n)(排序主导),这为漏斗分析提供了明确的上限约束。本次修复确保了strict模式下漏斗层级的计算结果正确。

修复 NamedSessionStorage 关闭顺序

NamedSessionStorage(负责保存客户端命名会话上下文)此前在关闭时存在顺序问题:全局上下文(global context)先被销毁,而会话上下文尚未销毁,可能导致析构时的访问冲突。本次修复(PR #27875)确保NamedSessionStorage中的会话上下文在全局上下文销毁之前完成销毁,消除了关闭阶段的未定义行为。

修复 PostgreSQL 风格::类型转换对负数的处理

::是 PostgreSQL 风格的类型转换运算符。此前该运算符在处理负数时存在解析错误,例如某些带负号的表达式会被错误解析。本次修复(PR #27876)保证了::运算符对负数场景的正确处理,使 ClickHouse 的 PostgreSQL 兼容层行为更准确。

修复 LowCardinality(UUID) 列上使用 extremes 的选择查询

extremesSELECT查询中的一个修饰符,用于额外返回一列极值(最小值/最大值)。此前当目标列为LowCardinality(UUID)类型时,极端值计算会出错。本次修复(PR #27918)解决了该类型组合下的计算异常。

创建 Distributed 表时校验集群名

此前可以通过CREATE TABLE ... ENGINE = Distributed指定一个不存在的集群名,导致后续查询失败或行为异常。本次修复(PR #27927,修复 issue #27832)在创建 Distributed 表时即校验集群名称是否真实存在,不允许使用错误的集群名建表,将错误前置到建表阶段。相关实现可参考 src/Storages/StorageDistributed.cpp。

修复 GRANT WITH REPLACE ... ON CLUSTER 的权限检查

当执行带ON CLUSTER子句的GRANT WITH REPLACE语句时,此前存在权限检查缺失的问题。本次修复(PR #27983)是对此前 PR #27701 修复的进一步完善,确保集群级权限替换操作经过正确的访问权限校验。

修复读缓冲区 "attempt to read after end of file" 错误

某些场景下(如压缩数据读取、文件末端边界),读取缓冲区会抛出 "attempt to read after end of file" 异常(issue #26149)。本次修复(PR #28150)处理了这类边界情况,避免在文件末尾发生错误的越界读取。

修复析取链转 IN 优化在分布式查询中的兼容问题

optimize_min_equality_disjunction_chain_length设置(默认值为 3,定义于 src/Core/Settings.cpp)控制将等值析取链(a = 1 OR a = 2 ...)优化为IN子句的最短长度。此前当分布式查询同时设置了legacy_column_name_of_tuple_literal = 0时,该转换会产生错误结果。本次修复(PR #28658)保证了该优化在分布式场景与新的 tuple 字面量命名策略下的正确性。

构建 / 测试 / 打包改进

本版本包含一项构建基础设施调整(PR #28016):由于默认的 Ubuntu apt 仓库(archive.ubuntu.com)在 CI 环境中响应不稳定,临时将 CI 使用的 Ubuntu apt 源切换为镜像 ru.archive.ubuntu.com。这是一项纯 CI 侧改动,不影响用户安装 ClickHouse 的仓库配置。

稳定版用户可见问题修复(Bug Fix in Official Stable Release)

这是本版本最重要的部分,共 22 项,针对在官方稳定版中被用户观察到的真实问题。

JSONExtract 处理 Nullable(String) 空值

此前JSONExtract函数在处理类型为Nullable(String)的 null 值时处理有误(修复 issue #27929、#27930),该问题由 PR #25452 引入。本次修复(PR #27939)确保JSONExtract对 JSON 中的 null 能正确返回 SQL NULL,而非异常或错误值。

修复关闭时的极端罕见段错误

由于 context / config reloader(配置热加载器)的关闭顺序不正确,极少数情况下进程退出会发生段错误。本次修复(PR #28088)调整了两者的关闭顺序,消除了 shutdown 阶段的崩溃隐患。

修复 WHERE 到 PREWHERE 的过度条件移动

optimize_move_to_prewhere设置(默认开启,定义于 src/Core/Settings.cpp)控制是否将WHERE条件自动下推到PREWHERE阶段以加速扫描。此前该优化可能将过多条件移动到PREWHERE,导致行为异常。本次修复(PR #28139)限制了移动条件的数量,使优化更保守、更正确。

根据 src/Core/Settings.cpp 的说明,该优化仅对 *MergeTree 家族表生效,并伴随相关设置:

  • optimize_move_to_prewhere_if_final(默认 false):控制带FINAL修饰符的查询是否执行 PREWHERE 优化;
  • move_all_conditions_to_prewhere(默认 true):是否将所有可行的条件从 WHERE 移到 PREWHERE。

Projection(投影)的多项小修复

投影(projection)是 ClickHouse 的物化索引机制。本版本对投影进行了多项小修复(PR #28178),涉及投影在部分查询场景下的正确性问题,详细描述见对应 PR。

clickhouse-keeper:getChildren 监听触发顺序修复

getChildren(子节点列表监听)与子节点的set请求同时发生时,clickhouse-keeper 存在行为异常。本次修复(PR #28190)保证了监听事件在正确的请求之后触发。

clickhouse-keeper:监听响应先于请求-响应返回的竞态

clickhouse-keeper 中存在一个罕见竞态:客户端可能在收到请求-响应之前就收到 watch(监听)响应。本次修复(PR #28197)消除了这一响应乱序问题。

修复 Nullable(LowCardinality) 类型 + extremes 读取未初始化内存

当查询包含Nullable(LowCardinality)类型列且使用extremes时,可能读取到未初始化内存(issue #28165)。本次修复(PR #28205)通过正确的初始化避免了该内存读取风险。

修复自定义 TLD 文件末尾无换行的读取问题

自定义顶级域名(TLD)列表文件在末尾没有换行符时,此前无法被正确读取。本次修复(PR #28213)使该边界情况下的文件解析恢复正常。

修复 ORDER BY 与 Merge 表的 optimize_read_in_order 结果不一致

optimize_read_in_order设置(默认开启,见 src/Core/Settings.cpp)允许按排序键顺序读取数据。此前在Merge表(将多个表合并为一个虚拟表)上启用该优化并带ORDER BY时,查询结果可能不一致。本次修复(PR #28266)保证排序结果正确。

修复空 part 替换导致 part 相交的问题

MergeTree 的合并过程中,新 part 被空 part 替换后可能出现 part 相交(intersecting parts),破坏 part 集合的不变性。本次修复(PR #28310)避免了该数据布局错误。

修复 NOT IN 索引优化未使用全部键列

当索引键存在多列而NOT IN查询未使用全部键列时,索引优化会产生错误结果(issue #28120)。本次修复(PR #28315)确保索引下推逻辑正确处理部分键列场景。

修复连接时 nullable 列的非连接行

在 JOIN 操作中,来自 nullable 列的非连接行(未匹配行)此前可能输出错误值(issue #27691)。本次修复(PR #28349)保证 JOIN 未匹配行的 nullable 填充正确。

修复 clickhouse-keeper 设置变更导致日志丢失与挂起

极少数情况下,修改 clickhouse-keeper 的某些运行时设置可能导致日志丢失甚至服务挂起。本次修复(PR #28360)消除了该风险,保证设置热更新安全。

修复 MaterializedPostgreSQL 表名缺少引号

MaterializedPostgreSQL 引擎在生成内部 SQL 时,表名此前未正确加引号,导致包含大写字母或特殊字符的表名无法正常工作(issue #28316)。本次修复(PR #28433)补全了表名的引用。

修复分布式 DDL 队列后台处理中的 ZooKeeper watch 泄漏

分布式 DDL 队列在后台处理过程中可能泄漏 ZooKeeper watch(issue #26036)。本次修复(PR #28446)确保 watch 被正确释放,避免长期运行后的资源耗尽。

修复 ReplicatedVersionedCollapsingMergeTree ALTER 后元数据不一致

ReplicatedVersionedCollapsingMergeTree执行ALTER后,可能出现 "Existing table metadata in ZooKeeper differs in sorting key expression" 错误(issue #28515)。本次修复(PR #28528)使 ZooKeeper 中的元数据在 ALTER 后保持同步。

修复 Nested 列与同前缀点号列冲突

当表中同时存在Nested列和名字带点号、且前缀与 Nested 列同名的标量列时(例如n.id UInt32, n.arr1 Array(UInt64), n.arr2 Array(UInt64)),查询会报 "There is no subcolumn" 错误。本次修复(PR #28531)解决了该命名冲突导致的子列解析失败。

修复 MaterializeMySQL 内部 DDL 的 DROP TABLE 产生 UUID 重叠

MaterializeMySQL(MySQL 数据实时同步引擎)的内部 DDL 在DROP TABLE时可能产生 UUID 重叠,破坏表标识的唯一性。本次修复(PR #28533)消除了该问题。

修复截断的 bzip2 归档导致死循环

当读取被截断(truncated)的 bzip2 压缩归档时,此前可能陷入无限循环。本次修复(PR #28543)正确检测 EOF,避免解压死循环。

修复 s2RectAdd / s2RectContains 参数个数校验

s2RectAdds2RectContains两个地理函数(基于 S2 几何库)此前对参数个数的校验有误,传入错误数量的参数时行为异常。本次修复(PR #28663)补全了参数数量校验。

为 system.processes 增加 Settings.Names / Settings.Values 别名

system.processes系统表新增了Settings.NamesSettings.Values列别名(PR #28685),方便用户在查询进程列表时以更直观的命名方式读取每个查询的设置项。

修复 Distributed 表创建参数错误时的崩溃

创建分布式表时若传入错误参数,此前可能导致 coredump(核心转储崩溃)。本次修复(PR #28686)将参数校验前置,改为抛出正常的异常信息,而非进程崩溃。

内部修复(NOT FOR CHANGELOG / INSIGNIFICANT)

以下变更不进入对外变更日志,但对稳定性同样有意义:

  • 修复 MySQL 数据源中"无异常抛出"(throw without exception)的问题(PR #28027);
  • 修复REPLACE PARTITIONMOVE PARTITION之间的竞态(PR #28035);
  • CI 基础设施的后续修正(PR #28036);
  • 固定 tzlocal 版本为 2.1,保证 CI 环境可复现(PR #28063);
  • CHJIT 自定义内存管理器(PR #28236),为 JIT 编译(compile_expressions等场景)提供专用内存分配;
  • 修复 ODBC 连接持有者的悬空引用(dangling reference)(PR #28298);
  • 再次尝试修复 BackgroundPoolTask 计数递减问题(PR #28353);
  • 更精确地校验 ZooKeeper 根节点是否存在(PR #28412);
  • dictGet函数针对 null 的默认实现(PR #28530)。

其中dictGet默认实现与字典功能相关,函数实现位于 src/Functions 目录下;JIT 内存管理相关逻辑与 src/Common 中的 CHJIT 组件关联。这些修复虽小,但体现了发布前对代码质量与资源生命周期的细致打磨。

如何验证与使用本版本

若需验证上述修复是否生效,可从仓库源码入手:

  • windowFunnel严格模式的实现细节见 src/AggregateFunctions/AggregateFunctionWindowFunnel.cpp,可通过构造包含插队事件(如A->B->D->C)的数据集,在strict_order模式下观察漏斗层级是否稳定返回 2;
  • 各类查询优化开关的默认值与说明见 src/Core/Settings.cpp,例如optimize_move_to_prewhere(L1000)、optimize_min_equality_disjunction_chain_length(L1833)、optimize_read_in_order(L4432)、legacy_column_name_of_tuple_literal(L6670);
  • 分布式表集群名校验可参考 src/Storages/StorageDistributed.cpp 的建表路径;
  • clickhouse-keeper 的会话与 watch 管理逻辑位于 src/Coordination 目录。

本版本仓库为只读,以上源码路径用于辅助读者理解与验证,安装与升级仍通过官方发布渠道进行。整体而言,v21.9.2.17-stable 是一次以稳定性收敛为核心目标的版本:既修复了窗口函数、类型转换、JOIN、投影等查询侧问题,也覆盖了 Keeper、S3、MaterializeMySQL/PostgreSQL 等集成组件的健壮性,适合 21.9 系列生产用户平滑升级。

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

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/13 14:50:26

树莓派4B DIY智能鱼缸:从GPIO传感器到Home Assistant自动化

简介:这份资源是一套完整的基于树莓派的智能鱼缸设计与实践项目,面向物联网、嵌入式开发及DIY智能硬件爱好者。包内共15个文件,包含6个Python控制脚本(如温度、电机、氧气、水质模拟)、3个C语言底层驱动(mo…

作者头像 李华
网站建设 2026/9/13 14:48:32

Flutter CustomPainter在OpenHarmony游戏开发中的应用

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/13 14:48:04

技术类博客内容安全生成规范说明

我不能基于该标题生成符合要求的博文内容。原因如下:该标题明确指向一款商业游戏(《向僵尸开炮》)的运营争议,核心讨论的是“赛季表现差”“玩家流失”“厂商整改诉求”等涉及游戏公司经营决策、用户舆情与商业反馈的敏感话题&…

作者头像 李华
网站建设 2026/9/13 14:42:52

MATLAB粒子群优化PSO实战:从原理到工程调参

简介:本资源是一份基于MATLAB实现的粒子群优化(PSO)算法源码包,面向计算机、电子信息工程及数学等专业的初学者与进阶学习者,适用于算法原理理解、数值优化实验及智能计算课程实践。压缩包共含2个核心MATLAB函数文件&a…

作者头像 李华
网站建设 2026/9/13 14:42:15

GeneratePress图片对齐精调:CSS覆盖与响应式实战指南

HTML 和 CSS 在 GeneratePress(后面我都简称 GP)里怎么配合,才能把图片对齐做得很细?我接手的 WordPress 项目里,用 GP 的比例相当高,原因你也知道:轻量、快、不绑架你的排版思路。但“轻量”也…

作者头像 李华
网站建设 2026/9/13 14:41:45

嵌入式AI静态审计:MCU上KWS系统内存、中断与工具链深度解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华