ClickHouse v24.10.4.191-stable 版本更新解析:合并策略、S3 行为与权限体系的关键变更
【免费下载链接】ClickHouseClickHouse® is a real-time analytics database management system项目地址: https://gitcode.com/GitHub_Trending/cli/ClickHouse
导读
本文基于 ClickHouse 官方 changelog 中v24.10.4.191-stable版本(git 提交927d50586cd,相对上一稳定版v24.10.3.21-stable)的完整更新记录,逐类解析该补丁版本带来的向后不兼容变更、新特性、性能优化、改进项与全部用户可见 Bug 修复,并结合当前仓库源码(如 MergeTreeSettings.cpp、SimpleMergeSelector.cpp、Settings.cpp)说明每个变更背后的实现细节与影响范围。读完本文,你将掌握该版本中min_age_to_force_merge系列设置的正确用法、s3_skip_empty_files默认值变更的升级影响,以及 Kafka/NATS/RabbitMQ 表引擎新增SOURCES权限后的授权要求,并了解并行副本、Dynamic/JSON 类型、备份恢复等方向的修复全貌。
版本概览:一次聚焦稳定性的补丁迭代
v24.10.4.191-stable是 ClickHouse 24.10 LTS 分支上的第四个稳定补丁版本,其变更范围涵盖了权限体系(1 项向后不兼容变更)、合并策略(1 项新特性)、查询执行与存储读取(2 项性能改进)、运维体验(7 项改进)以及 40+ 项用户可见的 Bug 修复。该版本未引入新的外部依赖或配置格式,升级风险主要集中于下述"向后不兼容变更"一节涉及的权限模型调整,以及s3_skip_empty_files默认行为变化。
向后不兼容变更:Kafka / NATS / RabbitMQ 表引擎纳入 SOURCES 权限体系
本版本最值得注意的变更(对应 PR#71250)是:Kafka、NATS、RabbitMQ 三种表引擎现在被纳入SOURCES权限层级,受其自身的 grant 控制。
在 ClickHouse 的访问控制模型中,SOURCES是一个全局权限类别。从源码可见,AccessType.h 中定义了M(SOURCES, "", GLOBAL, ALL),即SOURCES属于全局级别、可作为ALL授予,而 AccessRightsElement.cpp 中的处理逻辑会将READ/WRITE等 sources 类操作折叠进SOURCES。此前 Kafka、NATS、RabbitMQ 表引擎的创建并未被该层级约束,本次变更后,任何非默认(default)数据库用户若要创建这三种引擎的表,必须显式获得相应 grant。
升级前必须执行的授权操作
升级到该版本后,请对所有自定义数据库用户执行(以 Kafka 为例):
-- 授予使用 Kafka 表引擎的权限 GRANT SOURCES ON kafka.* TO user_name; -- 若希望该用户继续创建 NATS、RabbitMQ 表,需一并授予 GRANT SOURCES ON nats.* TO user_name; GRANT SOURCES ON rabbitmq.* TO user_name;SOURCES层级与SELECT、INSERT等权限相互独立,未授予前创建此类表会直接报权限不足错误。这也是本版本唯一要求"必须主动变更配置"的升级项,建议在发布流程中作为前提检查。
新特性:min_age_to_force_merge 组合的字节上限豁免
本次新特性(PR#73656)针对存量数据的强制合并场景:当min_age_to_force_merge_seconds与min_age_to_force_merge_on_partition_only同时启用时,分区级强制合并将忽略max_bytes_to_merge_at_max_space_in_pool的字节上限。
从源码看,该行为由三个设置协同控制(定义于 MergeTreeSettings.cpp):
| 设置项 | 类型/默认值 | 含义 |
|---|---|---|
min_age_to_force_merge_seconds | UInt64,默认0 | 若范围内每个 part 的年龄都超过该秒数,则强制合并 |
min_age_to_force_merge_on_partition_only | Bool,默认false | 仅对"整个分区"应用上述强制合并,不对子集生效 |
enable_max_bytes_limit_for_min_age_to_force_merge | Bool,默认true | 上述组合是否仍尊重max_bytes_to_merge_at_max_space_in_pool上限 |
本版本的新特性正是允许将该字节上限豁免关闭,使一个大分区可以一次合并到位,而不是被拆成多次受字节约束的小合并。对应地,SettingsChangesHistory.cpp 记录了enable_max_bytes_limit_for_min_age_to_force_merge默认值从false调整为true的变更历史(默认仍受限,需要显式关闭才能豁免)。
底层实现与配套限制
- 合并选择器层面:SimpleMergeSelector.cpp 的
allow()函数中,一旦min_age_to_force_merge满足且范围内最小年龄达标,直接返回true,绕过常规的大小比例(size-ratio)判定,从而允许通常不会被选中的不平衡合并。 - 分区选择层面:MergeTreeDataMergerMutator.cpp 的
getBestPartitionToOptimizeEntire()会统计各分区的min_age与total_size,其中is_partition_invalid判定会检查enable_max_bytes_limit_for_min_age_to_force_merge与max_total_size_to_merge——这正是"忽略字节上限"逻辑的落点。同时它要求合并池有足够空闲线程(受number_of_free_entries_in_pool_to_execute_optimize_entire_partition控制,默认25),避免抢占常规合并线程导致 "Too many parts"。 - 配套 Bug 修复:同一版本还修复了 PR
#72209描述的问题——此前min_age_to_force_merge_on_partition_only会对"已经合并为单个 part"的分区反复尝试合并而卡死,同时忽略那些含多个 part 的分区;本版本修正了该判定逻辑。
使用建议:该组合适用于"分区不再接收写入、需要按年龄一次性压实整个分区"的场景(例如 TTL 清理前的合并)。若分区大小会超过后台合并线程的字节预算,可评估将enable_max_bytes_limit_for_min_age_to_force_merge置为false;否则保持默认true更安全。
性能改进:并行副本与 Compact 子列读取
本版本包含两项性能优化,分别作用于查询执行期与存储读取期。
并行副本(Parallel Replicas)+ 本地计划:跳过 worker 端索引分析
对应 PR#72109:当查询启用并行副本且使用本地计划(local plan)时,索引分析(skip index analysis)只在查询发起方(initiator)执行一次,由协调者根据分析结果为各 worker 分配读取范围,worker 不再重复执行索引分析。这消除了分布式查询中每个副本各自做一遍索引分析的冗余开销。
与之相关的设置均在 Settings.cpp 中定义:allow_experimental_parallel_reading_from_replicas(L8266,别名enable_parallel_replicas,0关闭、1失败时静默降级、2失败时抛异常)、parallel_replicas_for_non_replicated_merge_tree(L8343,对非复制表启用并行读取)。同版本还附带修复了并行副本相关的多个缺陷,包括:单副本集群启用并行副本时的逻辑错误(PR#73403)、ANY JOIN与三表 JOIN 在并行副本下的数据一致性问题(PR#72393、#72510)、以及parallel_replicas_for_non_replicated_merge_tree在子查询中被忽略的问题(PR#73584)。
恢复 Compact 部件单列子列读取优化
对应 PR#72285:恢复了此前被意外删除的优化——在 Compact 格式部件(parts)中,当只读取单列的某个子列时,可以直接在子列级别进行优化读取(该优化最初由 PR#57631引入)。Compact 格式将多列数据打包存放,此优化避免了对无关数据段的整体读取,对subcolumns场景(如 JSON/Dynamic 列路径、Nested子列)的查询吞吐有直接帮助。同版本还修复了optimize_functions_to_subcolumns优化开启后若干类型不匹配问题(PR#72394)与tupleElement在LowCardinality元组上的报错(PR#73548),保证子列优化的正确性。
改进项:运维与对象存储体验优化
本版本共有 7 项常规改进,可归纳为四类:
1. 容器环境噪音消除
修复了 ClickHouse 在 Docker 容器中因受限 syscall 向 stderr 打印get_mempolicy: Operation not permitted的问题(PR#70900)。容器环境(如 gVisor、受限 seccomp profile)下常见的 NUMA 相关 syscall 失败不再产生误导性告警,日志更干净。
2. 对象存储行为修正与防御
removeObject/removeObjects非幂等修复(PR#71529):网络错误导致重试时,对象可能已在先前尝试中被删除,从而出现object not found。本次为相关存储路径补上重试语义处理,避免误判为异常。- Azure Iceberg Writer 兼容读取(PR
#72277):Azure 侧 Iceberg Writer 生成的元数据(manifest)不符合规范时,现在会尝试用 v2 reader 读取 v1 格式的元数据,并在 manifest 缺少必需字段时明确报错,而不是静默产出损坏数据。 - GCS
AuthenticationRequired错误支持(PR#72753):S3 客户端现在可以识别 GCS 返回的AuthenticationRequired错误。对应实现位于 S3/Client.cpp 的checkIfCredentialsChanged(),将凭证变更检测扩展到该异常名,触发凭证刷新逻辑。 - 备份/恢复时的 S3 响应解析参数(PR
#72778):新增 S3 请求设置http_max_fields(默认1000,见 Settings.cpp)、http_max_field_name_size(默认4 * 1024,Settings.cpp)与http_max_field_value_size,用于解析备份/恢复过程中 S3 API 响应中的多字段与超长字段,防止大响应头导致解析失败。 - Keeper multi 请求加速清理(PR
#73357):ObjectStorageQueueMetadata的清理线程改用 Keeper multi 请求批量提交,减少元数据清理时的 RTT 开销。
3. 缓存内存估算修正
改进了 cached marks(标记缓存)的内存占用近似算法(PR#72630),使缓存的内存统计更接近真实占用,降低因估算过高导致的缓存容量被压低或内存跟踪失真的情况。
4. 版本元数据
version_helper现在由每次提交填充(PR#74399),确保版本信息元数据与代码提交保持一致,便于构建与诊断时追溯。
Bug 修复全览:四十余项用户可见缺陷
本节按主题归类该版本全部用户可见修复(均针对官方稳定版中的行为缺陷),便于对照自己的业务场景排查升级收益。
合并、分区与数据一致性
ATTACH PART去重不再卡住(PR#65636):在ATTACH PART查询中被去重(deduplicated)的部件不再残留attaching_前缀,避免后续操作把正常部件误判为半成品。ALTER TABLE REPLACE/MOVE PARTITION后无停顿(PR#72024):后台任务调度取到了正确的设置,不再出现替换/移动分区后的不必要暂停。MOVE PARTITION ... TO TABLE格式化修复(PR#72080):开启format_alter_commands_with_parentheses时,MOVE PARTITION命令现在能正确格式化输出。- 动态列合并大小计算(PR
#71526及后续#72211):宽表(wide part)中 Dynamic 与 JSON 类型列的字节大小统计被修正;垂直合并(vertical merge)中的同类计算也同步修复。 ALTER DELETE/ mutations 与物化_block_number(PR#72261、#72854):开启enable_block_number_column后,基于物化_block_number列的ALTER DELETE与 mutation 均不再异常。- 空 Variant 禁止创建(PR
#72454):CREATE TABLE中不允许定义没有任何变体的空Variant类型,提前在 DDL 阶段拦截。
S3 与对象存储读取
s3/s3Clusterglob 结果不完整(PR#71947):当 S3 URI 含 glob 模式(如pattern/*)且桶中存在 S3 Console 自动创建的pattern/空对象时,s3/s3Cluster函数可能返回不完整结果或抛异常。同时s3_skip_empty_files默认值由false改为true。该设置在 Settings.cpp 中定义为:0时SELECT遇到与请求格式不兼容的空文件会抛异常,1时直接返回空结果。变更历史记录于 SettingsChangesHistory.cpp("We hope it will provide better UX")。升级后空文件将默认被跳过,行为更友好,但若你的查询依赖"空文件报错"来发现数据缺失,需在升级说明中注明此行为变化。_etag列过滤失效(PR#73353):从s3存储与表函数读取时按_etag列过滤现在正常工作。- S3 Express 支持修复(PR
#73777):此前 S3 Express 目录桶场景被破坏,本版本恢复支持。 - glob 解析健壮性(PR
#72572、#73569):单个元素的 glob(如{a})与"枚举 glob 后紧跟范围 glob"的解析均被修复,后者对应 issue#73473。
Dynamic / JSON 类型与格式
- Pretty JSON 中 Dynamic 值序列化(PR
#71923):修复 Pretty JSON 输出 Dynamic 值的序列化错误。 - Dynamic 列结构一致性(PR
#73644):修复Nested columns sizes are inconsistent with local_discriminators column size逻辑错误,消除数据不一致隐患。 - Dynamic/Object 结构反序列化(PR
#73767):修复CANNOT_READ_ALL_DATA异常。 - squashing 前类型/路径上限判断(PR
#73388):未达到类型数/路径数上限时,新类型不再被错误写入共享 variant/shared data。 - Tuple 解析重复 JSON 键检测(PR
#73082):解析 Tuple 时检查重复 JSON 键,避免此前可能触发的Invalid number of rows in Chunk逻辑错误。 - 原生格式设置传播(PR
#73179):TCPHandler 将格式设置(如output_format_native_write_json_as_string)正确传播给 NativeWriter。
权限、备份与恢复
RESTORE权限过高(PR#71958):访问实体的RESTORE因未处理的局部 revoke 需要了多余权限,现已修复(对应 issue#71853)。REVOKE ALL ON *.*失败(PR#72872):目标访问实体含隐式授权(implicit grants)时无法执行REVOKE ALL ON *.*的问题已解决。BACKUP DATABASE db EXCEPT TABLES db.table解析(PR#72429):备份语句中EXCEPT TABLES子句的解析失败已修复。- 备份恢复潜在崩溃(PR
#72947):修复恢复过程中的潜在崩溃风险。 - 行策略报错信息优化(PR
#73739,NOT FOR CHANGELOG 分类):应用行策略时给出更清晰的错误消息。
并行副本与分布式查询
- ARRAY JOIN 分布式查询下发(PR
#72608):分布式查询含 ARRAY JOIN 时,follower 服务器的查询生成被修复(对应 issue#69276)。 - 单副本集群读取逻辑错误(PR
#73403):修复启用并行副本后从单副本集群读取时的逻辑错误。 EXPLAIN SYNTAX不再解释查询(PR#73634):避免分布式查询因处理阶段错误出现逻辑错误(对应 issue#65205)。EXPLAIN AST子查询仅允许 SELECT(PR#71982):子查询内的EXPLAIN AST只允许 SELECT,其他类型查询会触发Bad cast from type DB::ASTCreateQuery to DB::ASTSelectWithUnionQuery或Inconsistent AST formatting逻辑错误。parallel_replicas_for_non_replicated_merge_tree子查询失效(PR#73584):非复制表子查询中该设置被忽略的问题已修复。
JOIN、内存与并发安全
- GraceHashJoin 数据竞争(PR
#72233):修复导致 JOIN 输出可能缺行的数据竞争。 - SimpleSquashingChunksTransform 稀疏列崩溃(PR
#72226):处理稀疏列时罕见的崩溃已修复。 - ColumnDynamic::dumpStructure() 数据竞争(PR
#72278):ConcurrentHashJoin构造等并发场景下的数据竞争已修复。 - 内存跟踪高估(PR
#73081):MemoryTracking与MemoryResident之间的差值不再持续增长,修正内存跟踪偏差。 - 嵌套 Maps 创建内存占用(PR
#73982):修复嵌套 Map 创建时的高内存占用。 - 向量相似度索引创建数据竞争(PR
#73517):修复创建向量索引时的数据竞争。 - Dictionary 数据损坏崩溃(PR
#73535):字典数据源返回错误数据导致的分段错误(segfault)已修复。 - LIMIT BY COLUMNS 崩溃(PR
#73686):LIMIT BY COLUMNS查询的崩溃已修复。 - projection 别名逆序选择(PR
#74033):别名被另一别名引用且按逆序选择时未加入 projection 的问题已修复。 - 压缩 Memory 引擎子列读取崩溃(PR
#74161):从压缩 Memory 引擎表读取子列时的崩溃已修复(对应 issue#74009)。
表引擎、磁盘与协议
- library bridge 僵尸进程(PR
#71301):library bridge 崩溃后残留的僵尸进程已清理。 - PostgreSQL 生成列兼容(PR
#71396):修复旧版 PostgreSQL 报attgenerated列不存在的问题(对应 issue#60651)。 - plain_rewritable 磁盘事务回滚(PR
#71439):创建目录失败导致事务回滚时的NoSuchKey错误已修复。 - plain_rewritable 多实例共享(PR
#74059):使用 plain_rewritable 元数据的磁盘可在多实例间共享,初始化(S3 与 Azure)时对对象不存在的错误予以忽略,适配"一个实例读元数据、另一实例同时修改"的预期场景。 - ObjectStorageQueue 崩溃与兼容(PR
#73274、#73420):修复StorageObjectStorageQueue崩溃,以及其在 ZooKeeper / 旧版 Keeper 下的兼容问题。 - Keeper 内部通信 SSL 高级配置(PR
#72730):修复 Keeper 内部通信的高级 SSL 配置。 - Kafka 表引擎关键字参数(PR
#74064):修复用户以关键字参数形式指定 Kafka 表引擎配置时的解析问题。 - formatDateTime 正时区格式化(PR
#73091):修复标量函数formatDateTime对正时区(如 UTC+8)的格式化输出。 - UDF 用于旧分析器 JOIN 表达式(PR
#72179):修复旧分析器下 UDF 用于 JOIN 表达式的问题。 - 稀疏列解析崩溃(PR
#72891):开启enable_parsing_to_custom_serialization后解析错误数据到稀疏列的崩溃已修复(该设置定义于 Settings.cpp)。 - 不支持存储的事务崩溃(PR
#73045):对不支持事务的存储执行事务操作不再崩溃。
内部修复与测试稳定性(NOT FOR CHANGELOG)
该分类下的条目不直接影响用户可见行为,但影响 CI 与发布质量,简要列出供关注测试的读者参考:
- 并行副本相关:修复并行副本下的
ANY JOIN(#72393)、三表 JOIN(#72510)、Y 形 JOIN 的Context has expired错误(#72735)、loadPathPrefixMap线程池异常的 use-after-free(#72870),以及 PR 禁用时跳过特殊 PR 报文处理(#74402)。 - 写入路径相关:
PartitionedSink取消逻辑(#72126)、write buffer 的 finalize/cancel 修复(#72386)、缺失的 finalize 调用(#73279)、operations_to_execute改为 shared_ptr(#72400)。 - 依赖与配置同步:NuRaft 更新(
#72584)、google-cloud-cpp 子模块 sparse checkout(#72205)、Google Cloud 配置同步(#73545)、回滚 TTL 相关合并(#72599)、回滚导致 CI 崩溃的变更(#73738)。 - 测试修复:
03262_column_sizes_with_dynamic_structure测试抖动修复(#71931)、移除test_move_shared_lock_fail_keeper_unavailable抖动测试并扩展稳定测试(#72357)、test_storage_s3_queue升级测试更新(#73607)、ProfileEvents::Counters::setParent()数据竞争修复(#72518)、SettingsChangesHistory对实验性设置的禁用(#72519)、新增设置(#73281)、修复#63151中的条件判断(#73504)。
升级建议与总结
综合该版本变更,建议按以下清单规划升级:
- 权限:升级后立即为自定义用户补齐 Kafka、NATS、RabbitMQ 的
SOURCESgrant,否则相关表创建会失败(唯一必做项)。 - S3 行为:确认业务是否依赖"空文件抛错"语义——
s3_skip_empty_files默认值已变为true,空文件将默认跳过(返回空结果)。 - 合并策略:如需按分区年龄强制压实大分区,可组合
min_age_to_force_merge_seconds+min_age_to_force_merge_on_partition_only,并按需评估enable_max_bytes_limit_for_min_age_to_force_merge是否关闭字节上限。 - 并行副本:本次包含多项并行副本正确性修复(单副本、ARRAY JOIN、ANY JOIN、三表 JOIN),使用
enable_parallel_replicas的用户应优先升级。 - 存储/对象存储:S3 Express、
_etag过滤、glob 解析、ObjectStorageQueue 崩溃等修复对对象存储重度用户价值明显。
总体而言,v24.10.4.191-stable是一次典型的"低风险高收益"稳定补丁:无新功能型配置项变更(合并字节豁免为可选新特性),重点在于修复合并行副本、Dynamic/JSON、S3/对象存储等现代特性在真实负载下的正确性与稳定性。结合上述源码级分析,可据此评估升级窗口并准备对应的配置调整。
【免费下载链接】ClickHouseClickHouse® is a real-time analytics database management system项目地址: https://gitcode.com/GitHub_Trending/cli/ClickHouse
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考