ClickHouse v26.1.12.23-stable 版本深度解读:HTTP 预认证加固、S3 请求可观测性与 15 项稳定性修复
2026/9/18 23:57:18 网站建设 项目流程

ClickHouse v26.1.12.23-stable 版本深度解读:HTTP 预认证加固、S3 请求可观测性与 15 项稳定性修复

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

本篇文章基于 docs/changelogs/v26.1.12.23-stable.md 官方变更日志,围绕 ClickHouse 2026 年 1 月发布的稳定版 v26.1.12.23-stable(commite5aa07a1b9a,相对 v26.1.11.9-stable/1784404a5ac)展开。文章将完整解析该版本引入的 1 项向后不兼容变更、1 项新特性、2 项改进与 15 项用户可见 Bug 修复,并逐条结合仓库源码与配置实现,帮助运维与开发人员评估升级风险、合理配置新参数并理解底层修复原理。

一、版本总览:一次以"安全加固 + 可观测性"为主题的稳定版

v26.1.12.23-stable 是 26.1 分支的补丁稳定版,改动可归纳为三条主线:

  • 安全与资源保护:收缩 HTTP 预认证阶段的头部解析上限、新增头部读取总时限、限制 TCP 握手中 Hello 包字符串长度,并新增handshake_timeout_milliseconds服务端配置,从 HTTP 与 TCP 两侧共同压缩"未认证连接即可占用内存/线程"的攻击面;
  • 可观测性:为 S3 GET 请求新增两个直方图指标,接入system.histogram_metrics系统表与 Prometheus 端点;
  • 正确性与稳定性:覆盖合并算法、JSON 列 min-max 索引、S3Queue、ClusterDiscovery、Dynamic 类型序列化、轻量删除后的查询优化、Parquet 统计信息等多个模块的缺陷修复。

整体上该版本以修复与加固为主,不引入新的 SQL 语法或存储格式变更,适合在充分回归后平滑升级。

二、向后不兼容变更:HTTP 预认证内存占用加固(升级必读)

这是本版本中唯一标注为Backward Incompatible Change的改动(对应 PR#103285),直接关系到所有通过 HTTP 接口访问 ClickHouse 的客户端。

2.1 默认值变化

配置项旧默认值新默认值说明
http_max_fields1,000,0001,000HTTP 请求头部、查询参数与表单数据中允许的最大字段数量
http_max_field_name_size128 KB4 KB单个字段名的最大长度
http_max_field_value_size128 KB128 KB(不变)单个字段值的最大长度
http_max_request_header_size无(新增)10 MB所有 HTTP 请求头部(名称与值合计)的总大小上限
http_headers_read_timeout无(新增)30 秒读取全部 HTTP 请求头部的总时限

新默认值在源码中可查证:src/Core/Settings.cpp 中的定义:

DECLARE(UInt64, http_max_fields, 1000, R"( Maximum number of fields in HTTP request headers, query parameters, and form data.)", 0) DECLARE(UInt64, http_max_field_name_size, 4 * 1024, R"( Maximum length of a field name in HTTP request headers, query parameters, and form data.)", 0) DECLARE(UInt64, http_max_field_value_size, 128 * 1024, R"( Maximum length of a field value in HTTP request headers, query parameters, and form data.)", 0) DECLARE(UInt64, http_max_request_header_size, 10 * 1024 * 1024, R"( Maximum total size of all HTTP request headers (names and values combined) in bytes.)", 0) DECLARE(Seconds, http_headers_read_timeout, 30, R"( Maximum time in seconds to read all HTTP request headers. This is a total deadline for the entire header parsing phase, not a per-read timeout. Protects against slowloris-style attacks where a client trickles header data slowly to hold connections open.)", 0)

2.2 变更动机与实现

该改动的核心目的是限制预认证阶段的内存占用。在 HTTP 连接完成认证之前,服务端必须先解析请求头部与表单字段;旧默认值允许单个连接携带高达 100 万字段、单字段名 128 KB,恶意或异常客户端可以用极小的网络流量触发服务端为其分配数百 MB 内存。

从实现上看,头部解析会构造 src/Server/HTTP/HTMLForm.cpp 中的表单对象,并分别读取三个上限:

: max_fields_number(settings[Setting::http_max_fields]) , max_field_name_size(settings[Setting::http_max_field_name_size]) , max_field_value_size(settings[Setting::http_max_field_value_size])

与之配套,http_max_request_header_size从总量维度兜底,http_headers_read_timeout(总时限而非单次读超时)则专门防御slowloris 式慢速攻击——攻击者以极低速率逐字节发送头部,长期占用连接与线程。

2.3 如何恢复旧行为

官方变更日志明确指出:"Users who rely on the previous higher limits can restore them via settings." 若你的客户端(如自定义 HTTP 长连接、携带大量 URL 查询参数或超大 Cookie 的网关)触发新限制,可通过三种方式恢复旧值:

方式一:查询级别(SET 语句)

SET http_max_fields = 1000000; SET http_max_field_name_size = 131072; SET http_max_request_header_size = 10485760;

方式二:HTTP 请求 URL 查询参数(单次请求生效)

curl 'http://localhost:8123/?query=SELECT%201&http_max_fields=1000000&http_max_field_name_size=131072'

方式三:服务端配置文件(全局生效),在config.xml<profiles><default>段中:

<profiles> <default> <http_max_fields>1000000</http_max_fields> <http_max_field_name_size>131072</http_max_field_name_size> <http_max_request_header_size>10485760</http_max_request_header_size> <http_headers_read_timeout>30</http_headers_read_timeout> </default> </profiles>

⚠️ 运维提示:恢复高上限会重新暴露该版本试图修复的预认证内存风险,建议仅在确认客户端确实需要且配合网关层头部白名单的情况下执行,并优先考虑收紧http_headers_read_timeout以保留 slowloris 防护。

三、新特性:S3 GET 请求直方图指标

本次新增两个直方图指标(对应 PR#102058),用于观测 S3 GET 请求的连接生命周期与字节消耗:

  • s3_read_request_duration_microseconds:S3 读请求连接从发起请求到连接关闭的持续时间(微秒);
  • s3_read_request_bytes:每个 S3 读请求连接上读取的字节数。

3.1 指标定义与桶(bucket)设置

指标在 src/Common/HistogramMetrics.cpp 中注册,预置桶如下:

Metric & S3ReadRequestDuration = Factory::instance().registerMetric( "s3_read_request_duration_microseconds", "Duration of S3 read request connections, from request initiation to connection close, in microseconds.", {1000, 10000, 50000, 200000, 500000, 1000000, 2000000, 5000000, 10000000, 60000000}); Metric & S3ReadRequestBytes = Factory::instance().registerMetric( "s3_read_request_bytes", "Bytes read per S3 read request connection.", {4096, 65536, 262144, 1048576, 4194304, 8388608, 16777216, 33554432, 67108864, 268435456});

3.2 查询与接入方式

指标可通过两个入口观测:

入口一:system.histogram_metrics系统表

SELECT metric, buckets, values FROM system.histogram_metrics WHERE metric IN ('s3_read_request_duration_microseconds', 's3_read_request_bytes');

入口二:Prometheus 端点(默认http://<host>:9363/metrics,或/metrics自定义路径),直方图以_bucket累加计数、_sum_count的形式暴露,可直接用于 Grafana 面板或告警:

  • 通过s3_read_request_duration_microseconds判断 S3 GET 连接耗时分布,定位慢请求或连接复用异常;
  • 通过s3_read_request_bytes观察单连接读取量,辅助评估缓冲/预取策略与带宽占用。

3.3 适用场景

该指标面向使用 S3 作为冷热分层存储(DiskS3)、s3()表函数或 S3Queue 引擎的部署。结合已有的S3ReadRequestsCountS3ReadRequestsErrorsS3ReadRequestsThrottlingS3ReadRequestsRedirects等 ProfileEvents(见 src/IO/S3/PocoHTTPClient.cpp),可以建立"请求量 + 错误量 + 耗时分布 + 字节量"的完整 S3 观测矩阵。

四、常规改进:线程内存与网络带宽

4.1system.stack_trace暴露每线程 untracked_memory

system.stack_trace系统表现在额外展示每个线程的untracked_memory(未被跟踪器统计的堆内存)字段(对应 PR#103065)。该字段能帮助定位"实际内存占用与MemoryTracker统计偏差"的场景——例如某些第三方库或裸malloc分配未计入查询级配额,排查内存超限与 OOM 时可直接按线程维度对比跟踪值。

4.2 带宽限制扩展至远程文件系统读写

max_network_bandwidth_for_usermax_network_bandwidth_for_all_users现在同样作用于远程文件系统的读取与写入(对应 PR#103080)。此前这两个设置主要约束网络传输(如分布式查询的中间结果),而本次将其语义扩展到 S3/对象存储等远程存储的 I/O 路径,使多租户场景下可以对用户/全局的远程存储吞吐进行统一限速,避免单一用户占满存储带宽影响其他查询。

五、Bug 修复全解:15 项用户可见缺陷

以下 15 项修复全部为 "user-visible misbehavior in an official stable release" 级别的回归修复,按主题归类如下。

5.1 查询正确性类

  • JSON 列 min-max 索引使用错误极值(PR#101918,关闭 issue#101700):JSON 列上创建的 min-max 索引使用了错误的 extremas,导致查询返回错误结果。修复后索引极值计算与列语义一致,涉及 JSON 列的过滤查询应重新验证结果一致性。
  • 时区调整溢出导致日期类型推断错误(PR#102674,关闭 issue#102601):时间戳在时区调整后发生溢出时,Date类型被错误推断。修复涉及日期类型的自动推断路径,受影响的是跨时区的DateTime/Date混用查询。
  • min-max count 投影与COUNT(*)优化在轻量删除后永久失效(PR#102900):执行一次轻量删除(lightweight delete)后,即使所有带删除掩码的 part 都已 merge 完成,minmax_count_projection与平凡COUNT(*)优化仍被永久禁用,性能损失持续存在。修复后,当带掩码的 part 全部合并消失,相关优化自动恢复。

5.2 稳定性与崩溃类

  • 合并算法在懒列复制下崩溃(PR#101036):当enable_lazy_columns_replication开启且ColumnReplicated列进入带迟到输入的 merge-sort 管道时,触发Logical error: isConst/isSparse/isReplicated assertTypeEquality崩溃。合并(OPTIMIZE/后台合并)期间可能触发,修复涉及合并管道的列类型断言逻辑。
  • 并发建表导致 S3Queue LOGICAL_ERROR(PR#102610):Shared database 上多个并发CREATE TABLE IF NOT EXISTS指向同一 S3Queue 表时抛出LOGICAL_ERROR。修复后并发 DDL 行为符合IF NOT EXISTS语义。
  • ClusterDiscovery 在静态集群无存活节点时抛服务端异常(PR#102661):配置中定义的静态集群短暂无存活节点时,ClusterDiscovery 逻辑抛出未处理的服务器异常,可能导致发现线程异常退出。

5.3 S3 / 对象存储类

  • S3 请求以ios_base::clear: unspecified iostream_category error失败且不重试(PR#102894):根因是 Poco 的BufferedStreamBuf::flushBuffer未处理 socket 层的短写(short write),导致请求直接报错而非走重试路径。修复后短写被正确识别,S3 请求恢复自动重试能力,对网络抖动场景的韧性明显提升。

5.4 安全与防护类

  • HMAC SQL 函数隐藏密钥(PR#102997,修复 issue#102927):HMAC函数的密钥不再在错误消息/日志中明文泄露,避免敏感凭据通过查询错误信息外泄。
  • TCP 预认证 Hello 包加固(PR#103284):未认证客户端发送的 Hello 包中各字符串(client name、default db、user、password、signature、quota key 等)长度上限被限制为64 KB,同时新增服务端配置handshake_timeout_milliseconds。源码见 src/Server/TCPHandler.cpp:
static constexpr size_t MAX_HELLO_STRING_SIZE = 64 * 1024; // ... readStringBinary(client_name, *in, MAX_HELLO_STRING_SIZE); readStringBinary(default_db, *in, MAX_HELLO_STRING_SIZE); readStringBinary(user, *in, MAX_HELLO_STRING_SIZE); readStringBinary(password, *in, MAX_HELLO_STRING_SIZE);

配套的handshake_timeout_milliseconds(默认 30,000 ms,即 30 秒)定义在 src/Core/ServerSettings.cpp:它是整个 TCP 握手阶段(Hello + Addendum)的墙钟总时限,限制未认证连接占用线程的时间,设置为0可关闭:

DECLARE(UInt64, handshake_timeout_milliseconds, 30000, R"( Wall-clock timeout in milliseconds for the entire TCP handshake phase (Hello + Addendum). Limits how long an unauthenticated connection can hold a thread. Set to 0 to disable.)", 0)

在 src/IO/ReadBufferFromPocoSocket.cpp 中实现超时判定:握手耗时超过阈值即抛出异常断开连接。这项修复与 HTTP 侧收紧遥相呼应,共同封堵"未认证即可消耗服务端资源"的攻击路径。

5.5 内存与资源管理类

  • 重新引入 ArrowMemoryPool 以避免内核 OOM(PR#102999):恢复 Arrow 内存池的接入,使 Arrow 格式处理在内存超限时抛出MEMORY_LIMIT_EXCEEDED,而不是放任分配直至触发内核 OOM。对使用format: Arrow/Parquet导入导出大文件的场景,服务端内存管理更加可控。
  • 普通 INSERT 不再过度申请 ConcurrencyControl 槽位(PR#102961):没有物化视图的普通 INSERT 此前会按max_threads而非max_insert_threads申请并发控制槽位与线程,在高吞吐 INSERT 集群上造成 CC 槽位饥饿与线程数激增。修复后按max_insert_threads申请,显著改善并发写入场景的资源调度。

5.6 格式与类型处理类

  • Dynamic 类型扁平化序列化修复(PR#102692,关闭 issue#101911):修复扁平化(flattened)Dynamic 类型在使用二进制编码数据类型时的序列化错误。
  • Native 格式中畸形扁平化 Dynamic 数据检查(PR#103392):读取 Native 格式时对畸形扁平化 Dynamic 数据增加校验,避免解析异常。
  • Parquet ColumnIndex 字符串列统计 min_value > max_value(PR#103334):修复 ParquetColumnIndex统计信息中 String 列出现min_value大于max_value的问题,此前可能导致基于统计的谓词下推产生错误结果。
  • url表函数填充_time(PR#103437):url()表函数现在会正确填充虚拟列_time(取自 HTTP 响应的 Last-Modified 等时间信息),使 URL 数据源可以直接按时间过滤。

六、构建 / 测试 / 打包改进

  • 升级 xz 至 5.8.3(PR#102607):打包依赖xz更新到 5.8.3,涉及压缩/解压库的版本同步,官方构建产物(二进制包、压缩包)均基于新版本生成。
  • CI:禁用 backport 分支的自动合并(PR#103160):属于 NOT FOR CHANGELOG 的内部改进,backport 分支不再自动合并,减少 CI 对 backport 流程的干扰,提升补丁分支管理的可控性。

七、升级与运维建议

  1. 升级前重点回归 HTTP 客户端http_max_fields(1,000,000 → 1,000)与http_max_field_name_size(128 KB → 4 KB)是本次唯一的兼容性风险点。升级前统计线上请求的字段数量与字段名长度分布;若存在超限,按 2.3 节方式在 profile 或网关层恢复上限,并设置http_headers_read_timeout兜底。
  2. 关注 TCP 客户端握手:使用原生 TCP 协议(clickhouse-client、官方驱动)的部署,确认客户端 Hello 包各字段均在 64 KB 内(正常客户端远低于此值);handshake_timeout_milliseconds默认 30 秒一般无需调整,仅在特殊网络环境(高延迟链路)下按需放宽。
  3. 开启 S3 可观测性:使用 S3 存储的部署升级后,立即验证system.histogram_metrics中两个新指标是否产生数据,并接入 Prometheus 建立耗时/字节量的基线告警。
  4. 回归测试清单:结合 5.1–5.6 的修复点,建议回归以下场景——JSON 列过滤查询、跨时区日期推断、轻量删除后COUNT(*)性能、S3Queue 并发 DDL、format: Arrow/Parquet 大文件读写、url()表函数查询、以及使用HMAC()的错误日志检查(确认密钥不再出现)。

八、参考文件索引

  • 变更日志原文:docs/changelogs/v26.1.12.23-stable.md
  • HTTP 新设置定义与默认值:src/Core/Settings.cpp
  • HTTP 表单解析上限的读取:src/Server/HTTP/HTMLForm.cpp
  • HTTP 设置说明注释:src/Server/HTTPHandler.h
  • S3 直方图指标注册与桶定义:src/Common/HistogramMetrics.cpp
  • TCP 握手超时设置:src/Core/ServerSettings.cpp
  • TCP Hello 字符串 64 KB 上限:src/Server/TCPHandler.cpp
  • S3 ProfileEvents 事件定义:src/IO/S3/PocoHTTPClient.cpp

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

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

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

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

立即咨询