
ClickHouse v20.8.3.18-stable 版本解析分布式存储策略、正则函数与聚合组合子修复全解读【免费下载链接】ClickHouseClickHouse® is a real-time analytics database management system项目地址: https://gitcode.com/GitHub_Trending/cli/ClickHousev20.8.3.18-stable 是 ClickHouse 20.8 系列的一个补丁版本在 v20.8.2.3-stable 基础上累计合入 2 项改进Improvement与 8 项缺陷修复Bug Fix覆盖分布式表存储策略、服务器关闭流程、聚合函数组合子、Decimal 运算精度、ALTER 变更语句与正则提取函数等多个核心模块。本文以 docs/changelogs/archive/v20.8.3.18-stable.md 为主线逐一拆解每个变更的技术背景、影响范围与底层实现并对照当前仓库源码给出可验证的实现依据帮助读者在升级或排查问题时快速定位相关行为变化。版本概览与升级背景该版本的全部变更均来自对主分支若干修复的 backport向后移植即先在较新的开发版本中修复问题再安全地移植到稳定的 20.8 分支。这意味着本版本没有引入新的语法或破坏性行为而是专注于稳定性的加固建议生产环境中的 20.8 系列用户升级。变更清单可归纳为四条主线分布式写入链路Storage Distributed 支持多卷存储配置、服务器关闭时更快结束 S3 请求、StorageFile(fd) 的 INSERT 崩溃修复聚合与正则引擎-Resample组合子极端参数下的段错误、extractAllGroups的内存超限报错数据正确性Decimal 乘法结果 scale 错误、ALTER UPDATE对 Nullable 列赋值常量的错误结果元数据与副本一致性ReplicatedMergeTree 建表失败后的数据目录残留、物化视图ALTER ... MODIFY QUERY丢失默认数据库名、LowCardinality 可空性检查。改进一Storage Distributed 支持多卷存储配置本版本将 #14839 移植到 20.8使Distributed 引擎表可以使用多卷multi-volume存储策略配置。在此之前若同一份 storage policy 同时被 MergeTree 表和 Distributed 表引用而该策略配置了多个卷Distributed 表在初始化存储时可能无法正确处理。从当前仓库的 StorageDistributed.h 可以看到这一设计意图的直接注释Storage policy may have several configured volumes, but second and other volumes are used for parts movement in MergeTree engine. For Distributed engine such configuration doesnt make sense and only the first (main) volume will be used to store data. Other volumes will be ignored.即对 Distributed 引擎而言只有策略中的主卷first/main volume被实际用于存放待发送的异步插入数据其余卷在 MergeTree 中是用于 parts 迁移的对 Distributed 无意义因此会被忽略。这样设计正是为了允许同一份多卷策略被 Distributed 与其他引擎共用避免为 Distributed 单独维护一套单卷策略。对用户的意义如果你在 config.xml 中定义了一个带多个卷的storage_configuration存储策略现在可以直接在CREATE TABLE ... ENGINE Distributed(...)中通过SETTINGS storage_policy policy_with_multiple_volumes引用它而无需担心初始化异常。Distributed 表写入的异步插入数据仍只会落在主卷上与 StorageDistributed.h 中storesDataOnDisk()依据data_volume ! nullptr判断的行为一致。改进二加速存在 S3 请求时的服务器关闭PR #14858 优化了当仍有进行中的 S3 请求时服务器的关停流程。ClickHouse 支持将数据存放在 S3 等对象存储上如 S3 磁盘、MergeTree over S3关闭服务器时需要等待在途请求结束若等待逻辑处理不当可能造成明显的关停延迟。该改进属于 shutdown 路径的收敛优化服务器在收到停机信号后会更快地打断或收敛与 S3 之间的在途 I/O缩短停机窗口。这对于将元数据或数据落在对象存储上的部署常见于 clickhouse-backup、S3 表函数及多级存储场景尤其有价值——停机时间越短滚动升级与故障切换越平滑。由于这是行为层面的优化20.8 用户无需调整任何配置即可受益。修复一-Resample组合子在超大参数下的罕见段错误问题现象Resample是聚合函数的组合子combinator语法为aggregate_functionResample(start, end, step)(aggregate_function_arguments, resampling_key)它将数据按[start, end)区间、以step为步长切分为若干桶分别对每个桶执行内层聚合最终返回一个数组。例如SELECT sumResample(0, 100, 10)(value, key) FROM t; -- 返回 [sum over key∈[0,10), sum over key∈[10,20), ...]PR #14562 修复的段错误触发条件是传入非常大的begin/end/step参数导致内部计算溢出。溢出后计算的桶数量total失控随后对状态数组的访问越界最终表现为罕见依赖参数取值的 SIGSEGV。源码级修复验证在 AggregateFunctionResample.cpp 中可以看到组合子对参数类型的严格校验最后一个参数resampling key必须是原生整数或整数类类型UInt*/Int*/Date/DateTime/DateTime64/Enum/Intervalbegin、end、step从参数表末尾三个位置取值。关键的防护逻辑位于 AggregateFunctionResample.hmax_elements 1048576单个 Resample 层的桶数上限超过即抛出ARGUMENT_OUT_OF_BOUND使用common::subOverflow/common::addOverflow对end - begin step做溢出检测对应total (end - begin step - 1) / step的计算sizeOfData()中使用common::mulOverflow校验total * size_of_data并设置max_state_size 1ULL 40防止嵌套 Resample 组合子如sumResampleResample把状态大小相乘到荒谬的量级。这些正是对「超大参数导致溢出」一类问题的系统性防线在构造阶段拒绝非法区间在状态分配阶段拒绝过大的内存请求从而从根上杜绝-Resample因算术溢出产生的段错误。使用建议-- 合法用法key 落在 [0, 60) 内每 10 一个桶 SELECT countResample(0, 60, 10)(x, key) FROM events; -- 非法用法会抛错而非段错误step 为 0 SELECT countResample(0, 60, 0)(x, key) FROM events;升级后超大参数场景将由「偶发段错误」变为「明确的异常信息」便于排查。修复二extractAllGroups偶发 Memory limit exceeded 错误问题现象extractAllGroupsVertical(s, regexp)与extractAllGroupsHorizontal(s, regexp)用于提取字符串中正则所有捕获组。PR #14889 修复了某些调用触发Memory limit exceeded的问题对应 issue #13383。旧实现在处理大量匹配时可能一次性申请超出内存限制的缓冲导致并非数据量过大、却被错误判为内存超限。源码级实现两个函数共用模板类 FunctionExtractAllGroups仅在ExtractAllGroupsResultKindVERTICAL/HORIZONTAL上区分extractAllGroupsVertical返回按出现顺序分组的二维数组SELECT extractAllGroupsVertical(abc111, def222, ghi333, ([^]|\\w)([^]|\\w)); -- [[abc, 111], [def, 222], [ghi, 333]]extractAllGroupsHorizontal返回按捕获组编号分组的二维数组SELECT extractAllGroupsHorizontal(abc111, def222, ghi333, ([^]|\\w)([^]|\\w)); -- [[abc, def, ghi], [111, 222, 333]]在 Horizontal 分支中代码先收集所有匹配的std::string_view到all_matches随后对输出 String 列做data_col-reserve(total_matched_groups_string_len)extractAllGroups.h。修复点在于不再让匹配过程无界增长内存占用同时 Horizontal 分支通过设置项regexp_max_matches_per_row对单行匹配次数设限超限抛出TOO_LARGE_ARRAY_SIZE异常extractAllGroups.h从而快速失败fail fast避免把「一行内极多匹配」演变成难以诊断的内存压力。Vertical 分支则按行边匹配边写列逐行推进pos时对空匹配也强制前移至少 1 字符std::maxsize_t(1, ...)避免无限循环extractAllGroups.h。extractAllGroupsHorizontal的注册信息语法、参数类型、示例可参见 extractAllGroupsHorizontal.cpp。使用建议若生产环境使用extractAllGroupsHorizontal解析日志如官方示例中的 HTTP 响应头解析且曾遇到偶发Memory limit exceeded升级到本版本即可消除误报同时可通过调低regexp_max_matches_per_row为解析结果加一道保险。修复三Decimal 乘法结果 scale 错误PR #14603 修复了Decimal 乘法结果列的 scale小数位数计算错误的问题。ClickHouse 的 Decimal 运算是定标scaled整数运算乘法结果的 scale 应为两个操作数 scale 之和若结果列的 scale 推导错误会直接导致数值多一位或少一位小数属于数据正确性缺陷。-- 修复前可能得到错误的小数位 SELECT toDecimal32(1.5, 1) * toDecimal32(2.5, 1); -- 期望 3.75scale2错误实现可能给出 0.375 或 37.5从本版本起乘法结果列的 scale 推导恢复正确涉及 Decimal 乘法、以及与常量/整数混合乘法的场景均需回归验证。建议在升级后对含 Decimal 乘法的报表查询做一轮数值比对。修复四ALTER UPDATE对 Nullable 列赋值常量导致错误值或段错误PR #14646 修复了ALTER TABLE ... UPDATE变更操作中赋值表达式含 Nullable 列且赋值为常量如UPDATE x 42时的两类问题写入错误的值或直接段错误。对应 issue #13634、#14045。-- 修复前x 为 Nullable 列时可能写入错误值或崩溃 ALTER TABLE t UPDATE x 42 WHERE id 1;问题根因是变更表达式求值路径对「常量赋值给 Nullable 目标列」的类型包装处理不当。本修复确保常量表达式在写入 Nullable 列时正确生成非空值且不再越界访问。任何依赖ALTER ... UPDATE做数据订正的用户都应升级并在升级后重点回归 Nullable 列的更新场景。修复五物化视图ALTER ... MODIFY QUERY丢失默认数据库名PR #14664 修复了物化视图执行ALTER TABLE mv MODIFY QUERY ...后元数据中遗漏默认数据库名的问题。物化视图的 SELECT 查询中若表名未显式限定数据库如SELECT * FROM source_table执行MODIFY QUERY重建元数据时新生成的查询可能丢失当前默认数据库的限定导致物化视图在后续刷新时解析到错误的库或依赖默认库上下文而出现行为漂移。修复后改写后的查询会正确保留默认数据库名确保「当前库」语义在元数据持久化后依然成立。涉及物化视图维护尤其跨库场景的部署建议升级。修复六ReplicatedMergeTree 建表失败后清理数据目录PR #14563 修复了CREATE TABLE创建ReplicatedMergeTree引擎表时若 ZooKeeper 操作抛出异常本地数据目录残留的问题。ReplicatedMergeTree建表需要先在 ZK 中创建副本节点、再在本地初始化数据目录。旧实现中若 ZK 步骤失败本地已创建的目录不会被清理留下「半成品」目录可能干扰后续同名建表或造成磁盘垃圾。修复后CreateQuery 失败路径会执行数据目录清理保证失败是原子的、可重试的。对频繁创建/删除复制表或 ZK 不稳定的环境此项修复可显著减少「幽灵目录」。修复七LowCardinality 可空性检查逻辑修正PR #14591 修复了LowCardinality 列的可空性Nullable判断此前单独调用lc-isNullable()或ls-getDictionaryPtr()-isNullable()都无法返回正确结果本版本补充了检查器checker使两处调用协同给出准确判断。LowCardinality 列的字典中嵌套了具体数据类型其可空性需要穿透字典才能确定。这一修复主要影响依赖可空性元数据的下游逻辑如类型兼容性检查、格式输出、部分函数对 Nullable 的处理属于低层正确性修复对使用者透明。修复八INSERT 到 StorageFile(fd) 触发 SIGSEGVPR #14887 修复了对StorageFile(fd)以文件描述符方式创建的 File 引擎表执行 INSERT 时的段错误。File 引擎表在通过file(fd)场景常见于管道、进程间通信创建时写入路径与普通文件路径不同。旧实现未正确处理该场景的写入流程导致 SIGSEGV。修复后INSERT INTO ... ENGINE File(fd)路径可正常工作。该场景相对小众但一旦触发即为进程级崩溃建议使用 File(fd) 做流式对外的用户升级验证。升级与回归建议综合本版本 10 项变更给出如下升级与回归要点关注点涉及变更回归建议分布式写入多卷策略、StorageFile(fd)对 Distributed 表执行SYSTEM FLUSH DISTRIBUTED验证 File(fd) INSERT数值正确性Decimal 乘法比对含 Decimal 乘法的查询结果小数位数据订正ALTER UPDATENullable 常量回归 Nullable 列 UPDATE 为常量聚合/正则-Resample超大参数、extractAllGroups覆盖极端区间参数解析超长日志行复制表ReplicatedMergeTree 建表清理模拟 ZK 异常建表确认无残留目录物化视图MODIFY QUERY 默认库名重建物化视图并检查 system.tables 元数据停机流程S3 请求关闭加速验证存在在途 S3 写入时的停机耗时上述所有变更均以 backport 形式进入 20.8 稳定分支不引入语法变更可安全纳入常规升级窗口。深入阅读对应实现可继续查看 AggregateFunctionResample.h、extractAllGroups.h 与 StorageDistributed.h 等文件完整变更清单见 v20.8.3.18-stable.md。【免费下载链接】ClickHouseClickHouse® is a real-time analytics database management system项目地址: https://gitcode.com/GitHub_Trending/cli/ClickHouse创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考