
ClickHouse v21.6.5.37-stable 变更日志深度解析14 项关键 Bug 修复的源码级解读【免费下载链接】ClickHouseClickHouse® is a real-time analytics database management system项目地址: https://gitcode.com/GitHub_Trending/cli/ClickHouse导读本文以 ClickHouse 官方 v21.6.5.37-stable 版本的 变更日志 为骨架逐条剖析该补丁版本中的 14 项 Bug 修复、1 项功能改进与 2 项内部优化。作为 v21.6.4.26-stable 的后续补丁版本v21.6.5.37 集中修复了 21.6 主版本引入的回归问题如LowCardinality参与IN时的类型转换崩溃、长期存在的正确性隐患如大整数CAST溢出返回错误结果以及分布式场景下的异常行为如Distributed Materialized View连接丢失列。读完本文你将掌握这些修复背后的代码机制、对应源码位置以及如何通过查询设置与 SQL 复现、验证相关行为。版本背景与修复概览v21.6.5.37-stable 是 ClickHouse 21.6 稳定分支的第 5 个补丁版本对比对象为 v21.6.4.26-stable。本次发布共包含 27 条条目按类别划分如下类别数量主要内容Improvement改进1后续 Bug 修复的准备工作PR #23518Bug Fix缺陷修复14分布式、格式、聚合函数、类型系统、复制表、查询计划等核心模块的正确性修复NOT FOR CHANGELOG内部改动2表达式编译与 ODBC 驱动适配所有修复均以 backport回移植方式合入稳定分支即先在主分支修复验证、再移植到 21.6 分支因此每一条都带有对应的 backport 跟踪 issue 与原始 PR 编号。这些改动集中体现了补丁版本只修 bug、不引功能的发布策略。Improvement为后续修复铺路本次唯一的 Improvement 条目来自 PR #23518作者 Nikita Mikhaylov其描述为这里将列出我准备在此 PR 中修复的所有 bug——这实际上是 ClickHouse 提交规范中用于聚合多个待修复问题清单的占位条目其价值在于把分散的 issue 汇总到单一 PR 中进行统一跟踪和批量修复属于流程性改进而非用户可见的功能变化。14 项 Bug Fix 逐条源码解读1. 修复Distributed Materialized View连接时的 Missing columns 异常修复 PR#24870作者 Azat Khuzhin当用户通过Distributed表查询底层的Materialized View并执行JOIN时可能抛出Missing columns异常。该问题的根因在于分布式查询在重组rewrite物化视图查询语句时用于连接的列在部分执行节点上未正确推导导致列名缺失。修复后分布式物化视图与JOIN的组合查询能够稳定返回正确结果。提示分布式物化视图的列一致性依赖Distributed表引擎对查询的改写逻辑见 src/Storages/Distributed 相关实现若在集群中出现Missing columns可优先排查视图定义与JOIN两侧表的列是否对齐。2. 修复 Protobuf 格式拆分嵌套消息的序列化错误修复 PR#25000对应 issue #24647作者 Vitaly BaranovProtobuf输入/输出格式在序列化被拆分split的嵌套消息时存在错误当一条 Protobuf 消息嵌套多层且字段被拆分到不同列时序列化结果与原始结构不一致。修复后Protobuf格式对嵌套Message类型的读写保持一致。该修复影响FORMAT Protobuf的input_format_protobuf_*系列设置与对应字段映射逻辑相关实现位于 src/Formats/FormatFactory.cpp 及 Protobuf 专属格式化器目录。3. 区分不同表的KILL MUTATION修复意外报错修复 PR#25025作者 Azat Khuzhin此前执行KILL MUTATION时如果集群中有多张表存在同名 mutation命令可能错误地取消其他表的 mutation 并抛出Cancelled mutating parts异常。修复后的逻辑在定位 mutation 时严格绑定表标识避免跨表误伤。这保证了 KILL MUTATION 语法KILL MUTATION WHERE database xxx AND table yyy在多表并发变更场景下的精确性。4. 修复CSVWithNames插入部分列时的报错修复 PR#25169对应 issue #25129作者 Nikita Mikhaylov使用CSVWithNames格式插入列的子集非全部列时会抛出错误。修复后CSVWithNames/CSVWithNamesAndTypes等带表头格式支持只提供部分列、按表头名匹配插入与CSV系列格式的input_format_skip_unknown_fields等设置协同工作。该行为对数据导入工具的兼容性很重要相关解析逻辑位于 src/Formats/FormatFactory.cpp。5. 修复安装脚本中的 TOCTOU 竞态修复 PR#25277作者 Alexey MilovidovTOCTOUTime-of-check to time-of-use是一类经典竞态漏洞程序先检查文件状态、再基于该检查结果执行操作而两者之间存在时间窗口可被利用。ClickHouse 官方安装脚本curl | sh模式中存在的该问题已被修复提升了 安装脚本 的安全性。6. 修复大整数CAST溢出CAST(1e19 AS UInt128)不再返回 0修复 PR#25279作者 Alexey Milovidov这是本次最值得关注的正确性修复之一。在旧版本中浮点数1e19大于UInt64的最大值18446744073709551615约 1.84e19但小于UInt128的上限CAST(1e19 AS UInt128)却错误地返回了0同时伴随 UBSan未定义行为消毒器报告。根因是大整数转换路径中对浮点中间值到 128 位整数的转换存在溢出处理缺陷。修复后SELECT CAST(1e19 AS UInt128); -- 正确返回 10000000000000000000该修复同时消除了 UBSan 报错说明问题本质是 C 层未定义行为整数溢出被正确规避。UInt128/UInt256的实现位于 src/Common/wide_integer.h浮点转换逻辑位于 src/Common/wide_integer_to_string.cpp读者可在其中看到大整数的内部表示与溢出边界处理。7. 修复joinGetOrNull在非空列上的行为修复 PR#25288对应 issue #24261作者 Amos BirdjoinGetOrNull与joinGet的区别在于当 join key 在连接表中不存在时joinGetOrNull返回NULL而joinGet直接报错。旧版本中当连接的取值列本身是非空列not-nullable时joinGetOrNull在 key 缺失场景下没有正确构造Nullable包装导致行为异常。修复后无论取值列是否允许 NULLjoinGetOrNull都能正确返回NULL。从源码看两个函数共用同一个 OverloadResolversrc/Functions/FunctionJoinGet.cpp通过effective_or_null布尔标志区分并在joinGetCheckAndGetReturnType中决定返回类型是否需包一层Nullable。官方文档示例src/Functions/FunctionJoinGet.cpp内嵌文档-- 构造 Join 引擎表 CREATE TABLE id_val(id UInt32, val UInt32) ENGINE Join(ALL, LEFT, id); INSERT INTO id_val VALUES (1, 11); -- joinGetOrNullkey 不存在时返回 NULL 而非报错 SELECT joinGetOrNull(id_val, val, toUInt32(1)), joinGetOrNull(id_val, val, toUInt32(999));注意Join引擎表及其joinGet系列函数对 key 的哈希布局敏感此处示例仅为验证修复后的 NULL 语义实际使用时请参照 Join 引擎文档 配置。8. 修复LowCardinality参与IN时的Bad cast崩溃修复 PR#25290对应 issue #25187作者 Nikolai Kochetov这是 21.6 主版本引入的回归问题。当LowCardinality列作为IN子句的左侧参数时会抛出Bad cast from type DB::ColumnLowCardinality to DB::ColumnVectorchar8_t根因在于IN操作符在比较路径中未对LowCardinality列做解包unwrap处理错误地试图将其直接转为ColumnVectorchar8_t。修复后LowCardinality参数参与IN查询可正常工作且不丢失低基数优化的性能收益。LowCardinality类型的实现位于 src/Columns/ColumnLowCardinality.h该崩溃的报错文案Bad cast from type来自 src/Common/typeid_cast.cpp 中的类型转换失败路径。9. 修复min/maxMap在Array/Tuple上的 Logical Error修复 PR#25298作者 Kruglov PavelminMap/maxMap系列函数在参数为Array或Tuple类型时抛出Cannot sum Array/Tuple的 Logical Error。修复后map 类聚合函数在计算键值对的 min/max 时不再误调用求和逻辑。相关实现位于 src/AggregateFunctions/AggregateFunctionsMinMaxMap.cppMap类型数据结构的定义可参考 src/DataTypes/DataTypeMap.h。10.SummingMergeTree支持SimpleAggregateFunction(LowCardinality)修复 PR#25300对应 issue #25134作者 Nikolai Kochetov此前在SummingMergeTree表中声明SimpleAggregateFunction(...)包裹的LowCardinality列会报错。修复后SummingMergeTree正确支持该组合CREATE TABLE t ( key UInt64, value SimpleAggregateFunction(sum, LowCardinality(UInt64)) ) ENGINE SummingMergeTree ORDER BY key;该修复让SummingMergeTree的预聚合列可以使用LowCardinality压缩存储兼顾写入聚合与存储优化。SimpleAggregateFunction的解析与存储逻辑位于 src/DataTypes/DataTypeAggregateFunction.h 及 src/AggregateFunctions 目录。11. 修复 ZooKeeper 断连时ReplicatedMergeTree后台任务阻塞重连修复 PR#25306作者 Alexander Tokmakov这是一个可用性关键修复。当ReplicatedMergeTree表失去 ZooKeeper 连接时后台任务如 merge、mutation会等待连接恢复反而阻塞了表尝试重连的流程形成互相等待。修复后ZooKeeper 连接丢失时后台操作会被强制停止表立即进入重连流程缩短了复制表的故障恢复时间。相关实现位于 src/Storages/StorageReplicatedMergeTree.cpp其 ZooKeeper 会话管理依赖 src/Common/ZooKeeper 目录下的客户端实现。12. 修复quantileDeterministic等函数的非确定性行为修复 PR#25313对应 issue #20480作者 Alexey MilovidovquantileDeterministic这类函数要求相同输入必须产生相同输出确定性因此它采用基于哈希的确定性水库抽样ReservoirSampler而非依赖随机数。旧版本中其行为可能出现非确定结果。修复后quantileDeterministic及同类函数保证了跨节点、跨运行的确定性。从源码结构看NameQuantileDeterministic与底层确定性采样器位于 src/AggregateFunctions/AggregateFunctionQuantile.h其有状态实现为 src/AggregateFunctions/ReservoirSamplerDeterministic.h。值得注意的是src/Core/ProtocolDefines.h 中专门定义了序列化quantileDeterministic状态的 skip degree说明该修复还涉及状态合并时稀疏化thinning的一致性——这正是非确定性问题的来源之一。13. 修复query_plan_filter_push_down优化丢失WHERE条件修复 PR#25370对应 issue #25368作者 Nikolai Kochetov这是查询优化器层面的关键正确性修复。新查询计划优化器Query Plan中的过滤条件下推优化在特定查询形状下会丢失WHERE条件导致返回错误结果集。该优化由设置query_plan_filter_push_down控制默认开启1。从源码看该设置定义于 src/Core/Settings.cppquery_plan_filter_push_down 1默认开启0 - 禁用1 - 启用官方注释明确该优化将过滤器沿执行计划向下移动且仅在query_plan_enable_optimizations 1时生效属于专家级调试设置。其核心实现在 src/Processors/QueryPlan/Optimizations/filterPushDown.cpp该文件包含约 1430 行逻辑针对FilterStep、JoinStep、AggregatingStep、WindowStep等各步骤实现安全的下推规则含分组集合、标识符归属检查等边界处理。如果你在生产环境中遇到加了WHERE条件但结果没过滤的可疑行为可以临时执行SET query_plan_filter_push_down 0; SET query_plan_enable_optimizations 0;复跑查询对比结果以确认是否触发该优化缺陷同时向官方提交 issue 附带EXPLAIN PLAN输出。14. 修复 DDL 中REPLACE列变换器的引号处理修复 PR#25391对应 issue #23925作者 Amos BirdREPLACE列变换器column transformer在用于 DDL如CREATE TABLE ... AS SELECT ... REPLACE(...)时格式化后的查询语句未正确加引号导致含特殊字符的表达式执行失败。修复后DDL 语句生成会对变换器内容做正确的引号转义。列变换器的解析与格式化实现位于 src/Parsers/ASTColumnsMatcher.cpp 与 src/Parsers/ASTColumnsTransformers.cppREPLACE变换器的完整语义见 SELECT 语句文档 中的COLUMNS变换器章节。内部改动NOT FOR CHANGELOG本版本还包含两条不面向用户的内部改动ExpressionActions 只编译必要部分PR #24273作者 Maksim Kita优化表达式动作ExpressionActions的编译范围避免为不参与计算的动作生成多余代码属于查询执行路径的性能打磨。ODBC 修复PR #25045 中的 ODBC 相关 helper的兼容性问题保证 ODBC 表函数 正常工作。升级建议与验证清单v21.6.5.37-stable 没有引入任何破坏性变更属于纯修复型补丁建议所有 21.6 用户升级。升级后建议按以下清单回归验证类型与聚合执行CAST(1e19 AS UInt128)应返回10000000000000000000用LowCardinality列执行IN查询不再崩溃minMap/maxMap传入Array/Tuple不再报 Logical ErrorSummingMergeTree可正常声明SimpleAggregateFunction(sum, LowCardinality(UInt64))列。Join 与分布式joinGetOrNull在 key 缺失且取值列为非空列时返回NULLDistributed表连接Materialized View不再抛Missing columns。复制与故障恢复模拟 ZooKeeper 断连ReplicatedMergeTree应快速进入重连而非被后台任务阻塞多表并发KILL MUTATION不再误取消。格式与 DDLCSVWithNames部分列插入、Protobuf 拆分嵌套消息序列化、DDL 中REPLACE列变换器均回归正常。查询优化器默认开启的query_plan_filter_push_down优化不再丢失WHERE条件如对结果存疑可用SET query_plan_filter_push_down 0对比验证。完整变更条目清单见仓库 docs/changelogs/archive/v21.6.5.37-stable.md更早版本的回溯可查阅 docs/changelogs 目录下的归档文件。【免费下载链接】ClickHouseClickHouse® is a real-time analytics database management system项目地址: https://gitcode.com/GitHub_Trending/cli/ClickHouse创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考