
ClickHouse v20.12.5.18-stable 补丁版发布解读50 余项 Bug 修复与稳定性加固全景分析【免费下载链接】ClickHouseClickHouse® is a real-time analytics database management system项目地址: https://gitcode.com/GitHub_Trending/cli/ClickHousev20.12.5.18-stable 是 ClickHouse 2020 年 12 月稳定分支20.12之上的一个补丁版本相对于上一补丁版 v20.12.5.14-stable它没有引入任何新功能而是聚焦于生产环境的稳定性包含 1 项容器镜像改进与 50 余项 Bug 修复覆盖查询正确性、MergeTree 家族读取与复制、数据类型与格式兼容、内存安全与崩溃修复、分布式与运维等多个维度。阅读本文你将系统了解该补丁版的发布背景、各项修复背后的根因与影响面并通过仓库源码确认关键机制如读取退避、谓词优化的底层实现从而为升级评估与排障提供依据。版本背景20.12 稳定分支的补丁发布脉络ClickHouse 采用功能版本 补丁版本的双层发布策略主版本号如 20.12承载新特性而-stable后缀的小版本如v20.12.5.18-stable则专门承载从主线 backport 回来的修复以保证生产用户可以以极低风险获得稳定性的持续改进。本版本相对上一补丁版 v20.12.5.14-stable 的改动全部为改进Improvement与 Bug 修复Bug Fix没有任何破坏性变更。这类补丁版的变更通常经 CI 全量测试后才被 backport 到稳定分支从源码结构看其内容大多来自 CHANGELOG.md 中对应主版本的后续修正。对于运行 20.12 系列的生产集群这是推荐跟进的小版本。唯一改进项ClickHouse Server 镜像固化 uid/gid本版本唯一的 Improvement 落在容器化部署侧在 clickhouse-server 官方 Docker 镜像中将clickhouse用户与用户组的uid/gid显式固定为 101PR #19096。这一改动对 K8s 与容器编排场景意义重大之前镜像内用户 ID 可能随基础镜像构建过程浮动导致挂载卷volume中由容器进程创建的文件属主不一致固定为 101 后不同版本镜像之间、镜像与宿主目录之间可以保持稳定的文件属主映射便于securityContext中配置runAsUser: 101也避免因属主漂移引发的权限类故障涉及 docker/server 目录下的镜像构建定义若你正在使用该目录中的 Dockerfile 构建私有镜像升级后应同步核对useradd/groupadd参数与工作负载的 UID 期望值。查询正确性修复谓词优化、索引分析与常量折叠该补丁版在查询优化与正确性上投入了大量修复以下按影响面归类说明。谓词优化器与非确定性函数PR #17273修复了非确定性函数indeterministic functions与谓词优化器predicate optimizer配合时产生错误结果的问题对应 issue #17244。谓词优化器会把WHERE条件中的公共谓词提前抽取、复用以降低重复计算但若谓词中嵌套了rand()、now()、sleep()这类每次调用结果可能不同的函数过早的公共子表达式提升会导致语义偏差。相关优化器实现在 src/Interpreters/PredicateRewriteVisitor.cpp 与 src/Interpreters/PredicateExpressionsOptimizer.cpp。修复后优化器在移动含非确定性函数的表达式时更加保守避免错误结果。带常量参数的二元函数索引分析PR #18373修复了带常量参数的二元函数在索引分析index analysis阶段出错导致查询结果错误的问题issue #18364。MergeTree 的跳过索引skip index与主键primary key裁剪都会对表达式做静态求值当表达式为col 1这类一列 一常量的二元形式时旧实现可能在推导可裁剪区间时产生偏差进而漏读或错读数据。该修复约束了这类二元函数在索引分析中的常量传播行为。分析阶段禁用子查询常量折叠PR #18446当子查询结果无法在分析阶段计算时禁用其常量折叠constant folding。此前优化器在无法求值时可能错误地假设子查询为常量导致后续计划错误。此项修复属于防御性修正主要影响含标量子查询的复杂查询。count()与SELECT权限的精细化PR #18233、PR #18232两个权限相关的修复值得 DBA 关注SELECT count() FROM table现在只需该表任一列可被选中即可执行issue #10639。此前若用户对表的列级权限不足即使count()不读取任何具体列也会被拒绝SELECT ... JOIN现在要求对每个参与 JOIN 的表都具有SELECT权限issue #17654收紧了 JOIN 场景的权限边界避免通过 JOIN 侧信道读取无权访问的表数据。now64()常量列转换PR #19316修复错误Cannot convert column now64() because it is constant but values of constants are different in source and result。now64()返回高精度时间在作为常量列参与表达式换算时源与目标的常量值可能因精度截断而不一致旧逻辑直接报错本次修复正确处理了该转换issue #7156 的延续。MergeTree 家族读取退避、复制与 mutation 的稳定性修复MergeTree 相关的修复是本次补丁版的重头戏其根因大多位于 src/Storages/MergeTree 目录下。读取退避导致的不完整查询结果PR #18216修复了在读取退避read backoff发生时MergeTree*查询可能返回不完整结果的问题issue #18137由 #16423 引入。当存储介质变慢时MergeTree 读取池会动态降低并发线程数日志中会输出Debug MergeTreeReadPool: Will lower number of threads旧实现在退避后未正确回收已分配的任务区间导致部分 mark 区间被丢弃。从源码看退避机制实现在 src/Storages/MergeTree/MergeTreeReadPool.cpp 的profileFeedback方法它根据每次读取的ProfileInfo字节数与耗时计算吞吐当吞吐低于max_throughput且事件间隔满足要求时累计事件达到min_events后递减current_threads并打出上述日志。相关阈值由 src/Core/Settings.cpp 中read_backoff_*系列设置控制设置项默认值作用read_backoff_min_latency_ms1000只关注耗时不低于该值的慢读事件read_backoff_max_throughput1048576读取带宽低于该值字节/秒时计为慢读事件read_backoff_min_interval_between_events_ms1000两个事件之间至少间隔该时间才会计数read_backoff_min_events2累计事件数达到该值后降低线程数read_backoff_min_concurrency1退避后的最低并发线程数下限对应的结构体BackoffSettings默认值可见于 src/Storages/MergeTree/MergeTreeReadPool.hmin_read_latency_ms1000、max_throughput1048576、min_events2、min_concurrency1。升级后若在慢盘环境中观察到上述 Debug 日志无需再担心查询结果被截断。ORDER BY与RIGHT/FULL JOIN子查询的 Pipeline 卡死PR #18550修复了子查询使用RIGHT或FULL JOIN后再ORDER BY时可能出现的Pipeline stuck错误右连接在流水线中需要先完整消费右侧数据与排序阶段的调度配合不当会造成死等。该修复调整了这类计划的流水线连接方式。ReplicatedMergeTree 并发 DDL 与空 part 处理多项修复针对复制表ReplicatedMergeTree并发ALTER与DROP可能导致 ReplicatedMergeTree 挂起PR #19237并发 DDL 在 zookeeper 队列中的调度顺序冲突现已修复ALTER在对应 mutation 被 kill 后挂起PR #18518由线程 fuzzer 发现修复了 mutation 终止信号与 ALTER 等待逻辑的竞态修复使用旧语法创建的 ReplicatedMergeTree 表移除空 part 的问题PR #18614issue #18582空 part 清理逻辑对旧语法建的表不生效导致空 part 残留mutation 在DROP/DETACH/REPLACE/MOVE PARTITION之后偶发挂起PR #19443与 #15537 的修复互补进一步封堵分区操作与 mutation 的竞态ALTER TABLE ... DROP PART part_name误删整个分区的去重块PR #18969issue #18874去重块deduplication block本应按分区与 part 隔离修复前 DROP PART 会清掉整分区的去重记录可能引发重新插入时的重复数据风险MODIFY TTL对旧语法 MergeTree 表不再静默无效PR #19064此前查询成功但实际无效果现直接拒绝执行避免误导。Attach Partition 与 mutation 重置PR #18935ATTACH PARTITION应重置该分区的 mutationissue #18804。否则被 detach 期间产生的 mutation 记录在 attach 后仍会生效与数据实际状态不一致。此修复保证附加回的分区从干净状态重新开始。system.parts的_state列PR #19346修复了查询system.parts的_state列时报LOGICAL_ERROR的问题——该列在系统表列定义中的顺序与实际存储顺序不一致导致读取错位。升级后即可正常查询该列。并发读取阈值为 0 时的 SIGSEGVPR #19528当把merge_tree_min_rows_for_concurrent_read/merge_tree_min_bytes_for_concurrent_read显式设为0或UINT64_MAX时可能触发 SIGSEGV现已在边界处防护。这两个设置控制单文件多线程并发读取的触发阈值定义在 src/Core/Settings.cpp默认merge_tree_min_rows_for_concurrent_read为20 * 8192行另有面向远程文件系统的独立阈值。数据类型、格式与外部集成修复MySQL 引擎数据类型转换与 FixedString 支持PR #18124、PR #18553两项修复与 MySQL 生态直接相关修复 MySQL 引擎MySQL(...)表函数/数据库引擎的数据类型转换问题PR #18124部分 MySQL 列类型映射到 ClickHouse 时类型推断错误导致读取异常为 MySQL 复制场景补充FixedString类型支持PR #18553此前从 MySQL 复制数据时遇到FixedString列会抛Code: 50, DB::Exception: Unsupported type FixedString(1)本补丁修复了该报错同时解决 issue #6556。这意味着使用 MaterializedMySQL 或相关 CDC 管道同步含CHAR(N)/BINARY(N)类型表时可正常落库为FixedString。类型转换与组合子的正确性修复CASTNullable 字符串到 Nullable DecimalPR #18718issue #7690修复Attempt to read after eof错误CAST无法从 nullable 字符串解析 decimal 时现在返回NULL而非抛异常*If组合子与一元函数 Nullable 类型PR #18806修复fIf族函数在参数含Nullable时类型处理错误groupUniqArray对 Enum 参数返回类型错误PR #19019issue #17875现保证返回与输入一致的正确数组类型JOIN 中非零默认值类型PR #19360issue #18197修复如部分 Enum 等默认值非零的类型在 JOIN 补默认列时取值错误JOIN 物化常量列PR #18982Join 尝试物化常量列但其他环节仍等待常量列二者不一致导致错误本次统一处理算术类型与字符串的精确比较栈溢出PR #19773Int64 vs String这类跨类型精确比较在极端输入下递归过深导致栈溢出改为迭代实现。LowCardinality 相关的系列修复LowCardinality是 20.x 高频使用的编码类型本版本密集修复了其边界问题向TinyLog引擎表插入 LowCardinality 列PR #19010issue #18629ignore()函数接收 LowCardinality 参数时报Expected single dictionary argument for functionPR #19016issue #14275启动时无法读取LowCardinality(Nullable(...))的压缩编解码器抛Attempt to read after EOFPR #19101issue #18340——属于老数据元数据兼容问题neighbor函数对 LowCardinality 参数结果错误PR #19617issue #10333。输入/输出格式修复HTTP 接口使用Template/CustomSeparated格式插入时报There is no checkpointPR #19072issue #19021行间插入input_format_parallel_parsing等在无显式检查点格式下误用检查点逻辑ORC 格式无限读取文件PR #19134issue #19095由 #10580 引入读取器在特定文件结构下不推进偏移导致死循环。崩溃、内存安全与安全性修复本补丁版修复了多个由 fuzzer 发现的严重内存安全问题升级价值极高修复项PR问题性质Uber H3 库潜在缓冲区溢出#19383引用上游 uber/h3#392特定地理坐标输入可触发越界读写addMonth构造参数导致越界读#19472月份加减在边界日期上发生内存越界issue #19441/#19413bitmapAndnot段错误#19713Roaring bitmap 差集运算在特定输入下崩溃arrayEnumerateUniq异常参数崩溃/死循环#19788异常参数导致无限循环或崩溃大整数实验特性函数段错误#19672Int128/Int256相关函数在特定参数下 segfaultCompressedWriteBuffer断开后的 use-after-free#19599连接断开后写入压缩缓冲的悬垂指针问题BloomFilter 索引崩溃#19884跳过索引中的布隆过滤器在特定列值下崩溃WHERE/PREWHERE使用嵌套列名崩溃#19763嵌套结构Nested列名在过滤条件下解析崩溃运维、分布式与日志相关修复DROP/DETACH TABLE ... ON CLUSTER cluster SYNC挂起PR #19572issue #19568SYNC 模式在跨节点执行时等待逻辑有缺陷现已修复异步分布式 INSERT 被network_compression_method全局非默认值拒绝PR #18776issue #18741异步分发走独立网络连接全局压缩方法设置与默认连接配置不匹配导致插入被拒现已对齐分布式批次在数据文件出现空数据块时标记为 brokenPR #19449防止空块导致的死循环重试system.text_log启用时可能死锁PR #19875issue #19874日志表写入与系统锁的相互作用导致死锁现已修复CREATE DICTIONARY的id表达式修复PR #19571字典主键表达式解析/生成错误关闭阶段的罕见死锁与卡顿clickhouse-local关闭挂起PR #18893、极罕见关闭死锁PR #18977、Logger 参数数量不匹配PR #18717network_compression_method相关修复见上表禁用不正确的optimize_move_functions_out_of_anyPR #18981该优化并非总是正确已在 src/Core/Settings.cpp 中标记为MAKE_OBSOLETEoptimize_move_functions_out_of_any, false。这意味着该设置已废弃且默认关闭若你在配置中显式开启过它升级后该行为不再生效。升级建议与验证要点建议升级范围所有运行 20.12 稳定分支且未跟进补丁版本的实例都应评估升级到 v20.12.5.18-stable特别是使用 MySQL 引擎/复制、LowCardinality、Template格式、ON CLUSTER DDL 的生产环境行为变更提示optimize_move_functions_out_of_any已被废弃MAKE_OBSOLETEMODIFY TTL在旧语法 MergeTree 表上将直接报错SELECT JOIN需要每个参与表的SELECT权限——这三处属于行为收紧升级前请检查相关 SQL 与配置验证重点升级后重点回归慢盘环境的大表扫描验证读取退避不再截断结果、MySQL 同步链路FixedString/类型转换、system.parts查询以及含RIGHT/FULL JOIN的排序查询日志佐证若需确认读取退避行为可在日志中检索MergeTreeReadPool: Will lower number of threads其实现细节见 src/Storages/MergeTree/MergeTreeReadPool.cpp 的profileFeedback。总体而言v20.12.5.18-stable 是一个小而关键的稳定性补丁包它没有新功能却用 50 余项修复覆盖了从查询正确性、数据一致性到内存安全的生产级风险。对于仍在 20.12 分支上的用户这是值得立即跟进的一版。【免费下载链接】ClickHouseClickHouse® is a real-time analytics database management system项目地址: https://gitcode.com/GitHub_Trending/cli/ClickHouse创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考