FEATURED · 精选文章

ClickHouse v21.3.20.1-lts 补丁版本解读:配额、序列化与函数层的稳定性修复

发布时间 / 2026/9/12 16:36:20
来源 / 创域科博编辑部
栏目 / 资讯中心
ClickHouse v21.3.20.1-lts 补丁版本解读:配额、序列化与函数层的稳定性修复 ClickHouse v21.3.20.1-lts 补丁版本解读配额、序列化与函数层的稳定性修复【免费下载链接】ClickHouseClickHouse® is a real-time analytics database management system项目地址: https://gitcode.com/GitHub_Trending/cli/ClickHouse本文以 ClickHouse 官方归档变更日志 docs/changelogs/archive/v21.3.20.1-lts.md 为骨架逐条剖析该 LTS 补丁版本中包含的配额Quota超限判定、LowCardinality 反序列化、fuzzBits位翻转崩溃、Protobuf 模式缓存数据竞争、StrictResize处理器卡死以及hasColumnInTable函数等稳定性修复。读完本文你将理解这些 bug 的触发场景、底层实现原理与修复方向并掌握在 21.3 LTS 分支上安全评估与升级的依据。版本背景LTS 分支的补丁发布机制该文档是docs/changelogs/archive/目录下归档的版本发布记录标题声明为ClickHouse release v21.3.20.1-lts与 v21.3.19.1-lts 对比。它属于 ClickHouse 的 LTS长期支持分支 21.3 系列的补丁版本LTS 分支在发布后只接收向后移植backport的缺陷修复不引入新功能从而保证生产环境的稳定性。从变更日志条目可以看出 21.3 LTS 补丁的筛选规则分类含义Bug Fix常规缺陷修复通常由用户报告并附带 issue 跟踪Bug Fix (user-visible misbehaviour in official stable release)官方稳定版中用户可见的错误行为属于高优先级回归NOT FOR CHANGELOG / INSIGNIFICANT内部修复或轻微问题不对外宣传但仍随版本发布每一个常规修复条目都会标注Backported in #xxxxx表示该修复原本合入主线master后再被移植到 21.3 分支这正是 LTS 分支只收修复、不收功能的具体体现。用户在评估是否升级时应重点核对后两类修复是否影响自身业务。常规 Bug Fix配额判定与 LowCardinality 反序列化配额Quota未达上限却被判定超限变更日志记录的第一个修复是Quota limit was not reached, but the limit was exceeded即配额尚未用完系统却错误地判定为超限并拒绝请求。配额机制在源码中的实现位于 src/Access/EnabledQuota.cpp。其核心逻辑是当用户在某个时间间隔内使用量超过配额上限时抛出QUOTA_EXCEEDED错误throwQuotaExceed错误信息形如 Quota for user ... has been exceeded: used/max否则仅记录用量。判定的关键代码为if (check_exceeded (used max)) throwQuotaExceed(user_name, intervals.quota_name, quota_type, used, max, interval.duration, end_of_interval);由于配额支持多种类型查询量、结果行数、结果字节数、执行时间等与多个时间间隔[src/Access/Common/QuotaDefs.h](https://link.gitcode.com/i/6ba62ace34980c08de13899639e774e1)中定义QuotaType枚举用量统计与上限比较之间存在取整、时间窗口切换、多类型累加等边界条件。该修复即针对这类边界条件下用量未超却误报超限的判定错误保证QuotaUsage见 src/Access/QuotaUsage.h的统计口径与拦截判断一致。实操建议生产环境可通过系统表system.quotas_usage、system.quota_usage实现在 src/Storages/System/StorageSystemQuotaUsage.cpp观察当前各用户的实际用量与配额上限确认升级前后行为差异。LowCardinality 数据在 Native 格式反序列化时空指针解引用第二个常规修复针对在 Native 格式下反序列化LowCardinality数据时可能发生空指针解引用null pointer dereference从而引发服务崩溃。LowCardinality是 ClickHouse 用于压缩高基数较低列的优化类型其序列化在 Native 格式中依赖字典索引与字典内容两部分的协同。当读取端遇到损坏或异常的数据块例如字典索引列缺失、列结构不匹配时若代码未对空列对象做防御性检查就会在解引用阶段触发段错误。该修复通过对反序列化路径中的空值检查将潜在的进程崩溃收敛为可处理的格式错误避免单个异常数据块拖垮整个服务器。用户可见行为修复fuzzBits 与 FixedString 的崩溃该补丁最重要的用户可见修复是当fuzzBits与多个相同的FixedString一起使用时会导致崩溃。fuzzBits是 ClickHouse 提供的随机位翻转函数其实现位于 src/Functions/fuzzBits.cpp签名fuzzBits(s, p)s为String或FixedStringp为0.01.0之间的常量浮点数表示每个位被翻转的概率原理使用pcg64_fast随机数发生器base/pcg-random/pcg_random.hpp逐字节生成掩码对输入字节做 XOR 实现按位翻转ptr_out[i] ptr_in[i] ^ mask返回与输入相同类型的结果每个数据行独立随机因此isDeterministic()与isDeterministicInScopeOfQuery()均返回false。从源码注释可以看到两个与本次修复直接相关的设计细节不启用常量展开默认实现注释明确说明useDefaultImplementationForConstants被刻意关闭——否则函数会只在单行上执行然后把同一份被随机化后的值复制到每一行结果上破坏逐行独立的随机语义固定概率参数为常量通过getArgumentsThatAreAlwaysConstant()将第二个参数固定为常量避免逐行解析概率值。当输入是FixedString时执行路径会通过ColumnFixedString按固定宽度n计算总大小input_rows_count * n并做mulOverflow溢出保护后整体进行位翻转。修复前在多个相同的 FixedString 值这一输入形态下常量/共享列处理与convertToFullColumnIfConst()展开之间可能产生未初始化的指针或越界访问进而崩溃。修复后该场景可正常返回随机翻转结果。对应测试与使用示例可见函数内嵌的FunctionDocumentationSELECT fuzzBits(materialize(abacaba), 0.1) FROM numbers(3)每次执行结果均不同例如abaaaja、a*cjab、aeca2A正好验证其非确定性与逐行独立随机特性。内部修复NOT FOR CHANGELOG / INSIGNIFICANT该分类下的修复虽然不对外宣传但同样是生产稳定性的重要组成部分。ProtobufSchemas 数据竞争修复了 src/Formats/ProtobufSchemas.cpp 中的数据竞争data race。该模块维护 protobuf 模式schema的全局导入缓存多个线程并发执行getMessageTypeForFormatSchema时会按(schemaDirectory, schemaPath, with_envelope)构造缓存键并查找/写入导入器。源码中可见修复采用的标准做法——所有对importers缓存的读写均置于std::lock_guard lock(mutex)保护之下同时区分了自动生成的临时 schema 与持久化 schema 的缓存策略避免缓存被无效导入器污染。数据竞争在并发查询同一 protobuf schema 时可能导致未定义行为修复后缓存访问具备线程安全保证。StrictResize 处理器流水线卡死修复了StrictResize处理器可能导致的流水线Pipeline卡死问题。相关实现位于 src/Processors/ResizeProcessor.cpp 与 src/Processors/ResizeProcessor.h。ResizeProcessor负责在多输入多输出处理器之间搬运数据块其prepare方法会轮询维护每个输入/输出端口的状态NotActive、Finished等并在所有输入都完成时结束流水线。StrictResize是要求严格同步多路数据流的变体若某个端口在未激活/未完成状态下状态机处理不完善就可能出现所有上游已完成、但下游仍在等待的死锁式卡死。该修复调整了端口状态转移逻辑保证严格变体下流水线仍能正常收尾。仓库中还带有针对性的单元测试 src/Processors/tests/gtest_strict_resize_finished_disabled_input.cpp可用于验证部分输入已完成/被禁用时处理器不会被卡死。arraySlice 空参数修复修复了arraySlice函数在收到NULL参数时可能出现的错误。arraySlice用于对数组按offset、length参数进行切片当切片参数为NULL时若类型推导路径未做空值处理会引发异常。修复后该函数对空参数具备正确健壮性避免因异常参数导致查询失败。hasColumnInTable 常量条件与非存在列查询修复了hasColumnInTable常量条件与非存在列场景下的查询问题。该函数实现在 src/Functions/hasColumnInTable.cpp用于判断某数据库表中是否存在指定列签名hasColumnInTable(database, table, column)三个参数都必须是const String返回UInt81表示存在0表示不存在实现通过DatabaseCatalog::getTable解析表对象再检查其内存元数据table_metadata-getColumns().hasPhysical(column_name)与hasAlias(column_name)物理列或别名列任一命中即返回1权限要求函数文档注释明确要求对目标表具有SHOW COLUMNS权限与DESCRIBE、SHOW CREATE TABLE相同否则抛出ACCESS_DENIED防止未授权用户探测列名嵌套结构语义对嵌套数据结构Nested的元素列返回1而对 Nested 结构本身返回0。本次修复针对的是查询优化器在hasColumnInTable作为常量条件时的短路行为当条件恒为false而查询中还引用了不存在的列时之前可能产生错误结果或异常修复后该组合场景可被正确解析与处理相关的常量条件与解析逻辑可参见 src/Analyzer/Resolve/resolveFunction.cpp。小结与升级建议v21.3.20.1-lts 是 21.3 LTS 分支的一个纯稳定性补丁没有新特性全部变更集中在缺陷修复上。按照变更日志的优先级升级决策可以参考以下清单配额用户核对system.quotas_usage用量与上限确认是否曾遇到用量未超却报 QUOTA_EXCEEDED的误判如有则本版本已修复LowCardinality Native 格式若存在跨版本数据传输或异常数据块导入注意本版本对反序列化空指针的加固使用fuzzBits数据脱敏/模糊测试场景尤其是对FixedString列做位翻转时本版本修复了多行相同值导致崩溃的问题Protobuf 格式导入导出高并发场景下 schema 缓存的数据竞争已通过互斥锁修复hasColumnInTable常用于动态判断列存在性的 ETL 脚本本版本修复了其与常量条件组合时的查询问题。完整的修复清单以归档变更日志 docs/changelogs/archive/v21.3.20.1-lts.md 为准如需了解 21.3 分支其他补丁可查阅docs/changelogs/archive/目录下同系列的版本记录并结合上述源码路径深入核对具体行为。【免费下载链接】ClickHouseClickHouse® is a real-time analytics database management system项目地址: https://gitcode.com/GitHub_Trending/cli/ClickHouse创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED — 相关阅读

相关资讯

LATEST — 最新资讯

最新发布

TODAY — 本日精选

新闻

WEEKLY — 本周精选

新闻

MONTHLY — 本月精选

新闻