ClickHouse v25.7.6.21-stable 发布解读:按日志通道启用 JSON 输出与 8 项关键修复回移
2026/9/18 13:52:51 网站建设 项目流程

ClickHouse v25.7.6.21-stable 发布解读:按日志通道启用 JSON 输出与 8 项关键修复回移

【免费下载链接】ClickHouseClickHouse® is a real-time analytics database management system项目地址: https://gitcode.com/GitHub_Trending/cli/ClickHouse

本文基于 ClickHouse 仓库中 v25.7.6.21-stable 的 changelog(docs/changelogs/v25.7.6.21-stable.md),逐项解读该 LTS 补丁版相对 v25.7.5.34-stable 引入的 1 项功能增强与 8 项 Bug 修复,并结合当前仓库源码说明这些改动的落点。读完本文,你可以判断该版本是否值得升级到生产环境,并掌握按日志通道开启 JSON 日志的完整配置方式。

版本定位:面向 LTS 分支的回移发布

该 release 的基线信息为:

  • 版本:v25.7.6.21-stable,构建提交a81134c5c92
  • 对比基线:v25.7.5.34-stable(a031c88152d)。

所有条目均以 “Backported in #...” 开头,说明这些改动最初合入主干,随后回移(backport)到 25.7 LTS 分支。对生产环境意味着:如果你在 25.7 LTS 上运行 ClickHouse,升级到 25.7.6.21 即可获得下列修复,而不需要跨大版本迁移。changelog 标题中的 “FIXME as compared to ...” 是 changelog 自动生成脚本的占位标记,表示这是两个 stable 提交之间的差异清单,不是需要人工处理的错误。

增强:JSON 日志只输出到指定通道

本版本唯一的 Improvement 条目:新增“仅对特定日志通道启用 JSON 格式”的能力。做法是在日志格式配置节中增加logger.formatting.channel,取值为syslogconsoleerrorloglog四者之一(对应 PR #86331,回移单 #86504)。

配置方式

ClickHouse 的日志输出由buildLoggers()拆分为多个通道:普通日志文件(log)、错误日志(errorlog)、syslog 与控制台(console)。在引入 channel 过滤之前,logger.formatting的 JSON 格式是全局生效的;现在可以通过channel子键将 JSON 格式绑定到单一通道,例如只让 errorlog 输出 JSON,其余通道保持人类可读的文本格式:

<logger> <level>warning</level> <console>1</console> <errorlog>/var/log/clickhouse-server/clickhouse-server.err.log</errorlog> <errorlog_level>warning</errorlog_level> <formatting> <channel>errorlog</channel> <type>json</type> </formatting> </logger>

其中type设为json是触发 JSON 输出的关键;channel省略时该格式配置对所有通道生效(作为全局回退)。

源码层面的实现

该能力的实现位于 src/Loggers/Loggers.cpp 的getFormatForChannel()

Poco::AutoPtr<OwnPatternFormatter> getFormatForChannel(Poco::Util::AbstractConfiguration & config, const std::string & channel, bool color) { Poco::Util::AbstractConfiguration::Keys keys; config.keys("logger", keys); std::string config_prefix_for_channel; std::string config_prefix_global; for (const auto & key : keys) { if (key != "formatting" && !key.starts_with("formatting[")) continue; if (config.getString(fmt::format("logger.{}.channel", key), "") == channel) { config_prefix_for_channel = "logger." + key; break; } ... } const auto & config_prefix = config_prefix_for_channel.empty() ? config_prefix_global : config_prefix_for_channel; if (config.getString(config_prefix + ".type", "") == "json") return new OwnJSONPatternFormatter(config, config_prefix); else return new OwnPatternFormatter(color); }

从源码结构可以确认几个要点:

  1. 代码同时遍历logger.formatting与索引形式的logger.formatting[0]logger.formatting[1]等键(第 80 行的starts_with("formatting[")判断),因此可以定义多组格式配置,每组各自声明channel
  2. 匹配优先级为“通道精确匹配优先、未声明 channel 的格式配置作为全局回退”(第 88-95 行),这与上文 XML 示例的行为一致;
  3. 每个通道的格式化器由getFormatForChannel(config, "log")之类的调用独立选择,如log通道在 Loggers.cpp 第 159-160 行 被构建为带格式器的OwnFormattingChannel

这一改动的典型适用场景是:运维侧希望 errorlog 以 JSON 结构输出以便被日志采集器(解析为结构化字段),同时保留 console/普通日志为文本格式便于交互式排障,无需为不同通道拆分多个进程或配置文件。

Bug 修复(1):并行副本协作判定改用collaborate_with_initiator

changelog 条目(回移单 #86112):使用distributed_depth作为 *Cluster 函数的指示器是不正确的,可能导致数据重复(data duplication);应改用client_info.collaborate_with_initiator(PR #85734)。

该修复在源码中的落点清晰可见。src/Interpreters/ClientInfo.h 中同时存在两个字段:

UInt64 distributed_depth = 0; ... /// For parallel processing on replicas bool collaborate_with_initiator{false};
  • distributed_depth记录查询经过 Distributed 转发的深度,它刻画的是“分布式查询嵌套层次”,与“该节点是否正在与发起副本协作并行处理”是两个不同语义——在多层转发、并行副本等组合场景下用它判断协作身份确实会误判;
  • collaborate_with_initiator是专为并行副本处理引入的标志位(注释即 “For parallel processing on replicas”),默认false

该标志的判定点位于 src/Interpreters/Context.cpp 第 8937-8942 行,任务型并行副本(task-based parallel replicas)的可用性与该标志取反/取直组合使用。标志的跨节点传递由ClientInfo::write/read序列化(见 src/Interpreters/ClientInfo.cpp 第 304 行写入、第 453 行读取),并有专门的序列化往返测试 src/Interpreters/tests/gtest_client_info_read.cpp 覆盖该字段的读回。

对用户的意义:此前依赖distributed_depth推断“我在集群查询的第几层”的自定义逻辑或旧版本行为,在涉及 Cluster 函数(如clusterAllReplicass3Cluster等按副本执行路径)时可能出现副本重复返回数据。升级到此版本后该判定改为显式标志,属于正确性修复,建议在多副本集群上重点验证。

Bug 修复(2):DatabaseReplicatedCREATE ... AS (SELECT * FROM s3Cluster(...))的逻辑错误

条目(回移单 #86266):在DatabaseReplicated环境中执行CREATE TABLE ... AS (SELECT * FROM s3Cluster(...))会触发逻辑错误,现已修复(PR #85904)。

这是“复制数据库 + 集群表函数”组合场景的修复:CREATE TABLE AS (SELECT ...)需要先在本地建表、再执行远程选择器把数据拉回来,而在DatabaseReplicated下建表动作本身还会在副本间同步,叠加s3Cluster这类集群化 S3 访问函数时,建表与数据读取的时序/身份判断出现了逻辑错误。如果你使用DatabaseReplicated做跨副本的湖仓外表批量导入,升级后可消除该路径上的报错。

Bug 修复(3):Unity Catalog 忽略非 Delta 表中的“怪异”数据类型 schema

条目(回移单 #86163,修复 issue #85699):Unity Catalog 在处理非 Delta 表时,现在会忽略带有不兼容(“weird”)数据类型的 schema(PR #85950)。

这属于容错性修复:此前遇到无法映射的数据类型时整个 schema 的处理可能被中断,现在对非 Delta 格式的表采取跳过策略,保证其余正常列可被读取。如果你通过 Unity Catalog 对接第三方 Iceberg 等湖表且偶发 schema 解析失败,此修复直接相关。

Bug 修复(4):index_granularity_bytes = 0FINAL+ skip index 抛异常

条目(回移单 #86291):当表(例如ReplacingMergeTree)以index_granularity_bytes = 0创建时,带 skip index 的FINAL查询会抛出异常,现已修复(PR #86147)。

index_granularity_bytes是粒度控制的字节阈值形式,设为0属于合法的边界配置(表示不按字节阈值触发新标记块)。此前该边界值与 skip index 在FINAL查询中的索引扫描路径组合时未做防护,导致直接抛异常。如果你的历史表曾使用该设置,升级后此类FINAL查询可恢复正常执行。

其余 4 项崩溃/正确性修复

changelog 中还有 4 项均为高优先级的稳定性修复,逐条说明如下:

1. 同一次 INSERT 中混合常量块与非常量块导致崩溃(#86308)

changelog 原文(PR #86230,回移单 #86308):修复单次 INSERT 中同时出现 const 与 non-const 块时的崩溃。

这类场景常见于异步插入攒批、或客户端一次性提交多个结构不同的 block(部分列是常量、部分不是)时。修复前服务端在合并处理时假设块类型一致,触发崩溃。对高吞吐批量写入(尤其配合INSERT批量协议或Buffer表)的集群,这是典型的可用性修复。

2.ALTER UPDATE Nullable(JSON)导致崩溃(#86348)

changelog 原文(PR #86281,回移单 #86348):修复对Nullable(JSON)列执行 mutation(ALTER UPDATE)时的崩溃。

Nullable(JSON)与 JSON 列的 mutation 路径涉及对每个非 NULL 值的重新序列化,属于 JSON 列支持中较边缘但可触发的组合。如果你在 JSON 列上加了Nullable并计划做后台 mutation(ALTER TABLE ... UPDATE),建议先升级再操作。

3. 物化视图同名重建后不工作(#86454)

changelog 原文(PR #86413,回移单 #86454):物化视图若被创建、删除后再以相同名称重新创建,可能出现不工作的情况。已修复(作者 Alexander Tokmakov)。

这是 MV 生命周期管理中的状态残留问题:drop 后再 create 同名 MV 时,内部某项与名称关联的状态未被正确清理/重建,导致新 MV 数据管道不生效。对运维自动化脚本(先 drop 后 create 的幂等建表流程)尤为关键。

4.Buffer表引起MergesMutationsMemoryTracking泄漏,以及query_views_log在 Kafka 流式读取下不记录(#86466)

changelog 原文(PR #86422,回移单 #86466):

  • 修复由Buffer表引起的MergesMutationsMemoryTracking内存跟踪对象泄漏;
  • 修复从Kafka等引擎流式读取(streaming)时system.query_views_log记录不正确的问题。

前者意味着长期运行的实例上,围绕 merge/mutation 的内存追踪会随Buffer表流量缓慢累积,属于典型的“慢泄漏”,升级后可恢复内存可观测性;后者让Kafka等流式源引擎的查询正确落进query_views_log,完善了基于该表的查询审计与 MV 血缘统计。

小结:这个补丁版解决了什么问题

v25.7.6.21-stable 相对 v25.7.5.34-stable 的变更可以归纳为三类价值:

类别条目面向场景
功能增强按通道启用 JSON 日志(logger.formatting.channel日志结构化采集,通道级格式控制
数据正确性collaborate_with_initiator替代distributed_depth判定并行副本 / *Cluster 函数场景防数据重复
数据正确性DatabaseReplicated+s3ClusterCTAS 逻辑错误复制数据库下集群湖表导入
数据正确性Unity Catalog 容错跳过非常规类型 schema湖仓表 schema 解析
数据正确性FINAL+ skip index +index_granularity_bytes = 0边界粒度配置的 FINAL 查询
稳定性INSERT 混合 const/non-const 块崩溃、ALTER UPDATE Nullable(JSON)崩溃、MV 同名重建失效写入路径、mutation、MV 生命周期
可观测性/内存MergesMutationsMemoryTracking泄漏、query_views_log流式源记录内存追踪、查询审计

升级建议:由于本版本包含一个可能引发数据重复的并行副本正确性修复(distributed_depth判定),在多副本集群上使用clusterAllReplicas类函数的用户应优先升级;使用DatabaseReplicated、JSON 列、Buffer表或物化视图自动化流程的用户同样建议升级。所有修复均已回移到 25.7 LTS 分支,升级成本仅为补丁版本切换,无需跨主版本。

【免费下载链接】ClickHouseClickHouse® is a real-time analytics database management system项目地址: https://gitcode.com/GitHub_Trending/cli/ClickHouse

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询