ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

ClickHouse v23.8.7.24-lts 版本解析:LTS 维护分支的六项关键 Bug 修复与构建改进

ClickHouse v23.8.7.24-lts 版本解析:LTS 维护分支的六项关键 Bug 修复与构建改进 ClickHouse v23.8.7.24-lts 版本解析LTS 维护分支的六项关键 Bug 修复与构建改进【免费下载链接】ClickHouseClickHouse® is a real-time analytics database management system项目地址: https://gitcode.com/GitHub_Trending/cli/ClickHouse导读本文基于 ClickHouse 官方发布说明v23.8.7.24-lts系统梳理 23.8 LTS 系列这一维护版本中包含的 1 项构建/测试/打包改进、6 项用户可见的 Bug 修复并结合当前仓库源码逐一剖析问题根因、修复思路与验证方法。读完本文你将理解system.tables的data_paths列语义边界、view()表函数与UNION查询的协作机制、FPC 压缩编解码器的防御性边界检查、RabbitMQ 表引擎的 TLS 连接配置以及 Kafka 表创建时 Kerberos 初始化的异常安全处理并能据此评估升级该 LTS 补丁版本的风险与收益。一、版本背景23.8 LTS 维护分支的定位v23.8.7.24-lts 是 ClickHouse 23.8 LTSLong Term Support系列中的第 7 个补丁版本基准提交为812b95e14ba与上一补丁版本 v23.8.6.16-lts077df679bed相比本版本不包含任何新功能FIXME语义下无 New Feature / Performance Improvement 条目全部变更集中在三类Build/Testing/Packaging Improvement构建与测试流水线改进1 项Bug Fix用户可见的官方稳定版本缺陷修复6 项NO CL CATEGORY / NOT FOR CHANGELOG未分类与内部流水线条目。这类纯修复的补丁版本正是 LTS 分支的核心价值在保持 SQL 语法与行为稳定的前提下持续收敛已知缺陷适合在生产环境无痛滚动升级。二、构建/测试/打包改进builder 容器不再拉取已变更的子模块发布说明Backported in #56733 — Do not fetch changed submodules in the builder containerPR #56689。ClickHouse 的依赖以 git 子模块形式托管在 contrib 目录下构建镜像builder container在每次构建时会拉取依赖快照。本次改进的核心是当构建环境的子模块状态未发生实际变更时跳过git submodule update中的重复拉取步骤从而缩短 CI 构建时间、降低网络抖动导致的构建失败概率。从仓库结构可以印证其影响面contrib 下包含上百个*-cmake目录与大量 [Empty subtree] 占位实际内容由 update-submodules.sh 在构建期同步子模块的拉取是构建链路中开销较大的环节。此类优化属于 CI 内部行为不影响最终二进制产物与用户可观察行为但能显著提升 23.8 LTS 分支后续补丁的发布节奏稳定性。三、六项 Bug 修复深度解析3.1system.tables的data_paths列不再引用远程数据源发布说明Prevent reference to a remote data source for thedata_pathscolumn insystem.tablesif the table is created with a table function using explicit column descriptionPR #55540。问题现象当用户通过表函数table function创建表并显式指定列描述时查询system.tables的data_paths列会引用远程数据源路径——例如remote()、url()、s3()等表函数创建的表本不应暴露底层远程文件系统路径。源码佐证在 src/Storages/System/StorageSystemTables.cpp 中data_paths列被定义为{data_paths, std::make_sharedDataTypeArray(std::make_sharedDataTypeString()), Paths to the table data in the file systems.}即其语义是表数据在文件系统中的路径。对于没有本地存储路径的表如临时表代码在 同一文件 L608-L610 直接insertDefault()返回空值而非推导出的路径同时 L765 的注释指出data_paths是唯一需要在查询时持有共享锁的列重命名可能改变普通表的路径。修复要点当表由表函数创建且携带显式列描述时data_paths不再被解析为远程数据源引用而是回退为不存在的本地路径集合。这一修复同时避免了远程元数据访问带来的额外开销与潜在的信息泄露面。验证方式-- 修复前可能看到远程对象存储路径 -- 修复后返回空数组 SELECT engine, data_paths FROM system.tables WHERE name remote_table;3.2view()表函数中UNION查询结果不完整发布说明Fix incomplete query result forUNIONinview()table functionPR #56274。问题现象view(subquery)表函数将子查询包装为表当子查询包含UNION含UNION ALL/UNION DISTINCT时读取结果可能不完整丢失部分行。源码佐证src/TableFunctions/TableFunctionView.cpp 是view()表函数的实现核心parseArgumentsL37-L49通过tryGetQueryArgument()提取子查询 ASTgetActualTableStructureL51-L65根据allow_experimental_analyzer设置选择InterpreterSelectQueryAnalyzer::getSampleBlock或InterpreterSelectWithUnionQuery::getSampleBlock推导结果列结构executeImplL67-L74用推导出的结构创建 StorageView读取时执行存储的 SELECT 并裁剪无用列。view()不存储数据仅保存查询并按需执行见 registerTableFunctionView 中的说明The resulting table does not store data, but only stores the specified SELECT query。UNION结果不完整的根因位于查询管道对 UNION 结果集的处理边界列名/别名推导与结果合并阶段修复后view()中多段UNION子查询可正确返回全部行。典型用法来自 TableFunctionView.cpp 源码文档SELECT * FROM view(SELECT name FROM months); SELECT * FROM remote(127.0.0.1, view(SELECT a, b, c FROM table_name));验证方式-- 修复前结果行数少于两段 SELECT 之和 -- 修复后完整返回 SELECT count() FROM view( SELECT number FROM numbers(1000) UNION ALL SELECT number FROM numbers(1000) ); -- 期望 20003.3 禁止向已有表添加Object(JSON)类型列发布说明Prohibit adding a column with typeObject(JSON)to an existing tablePR #56307同时关闭 issue #56095 与 #49944。问题现象此前用户可以对已存在的表执行ALTER TABLE ... ADD COLUMN x Object(JSON)该操作在生产数据上会引发不一致的存储行为JSON 对象的动态子列无法在存量数据上正确物化因此被官方判定为不合法。修复要点Object(JSON)类型现在仅允许在表创建时指定禁止通过ALTER向存量表追加。从数据结构上看Object(JSON)的动态 schema 需要在表元数据与数据目录初始化阶段就建立子列映射运行中追加会破坏这一一致性假设这与 ClickHouse 对动态类型谨慎演进的整体策略一致。验证方式CREATE TABLE t (id UInt64) ENGINE MergeTree ORDER BY id; -- 以下操作在本版本起被拒绝 ALTER TABLE t ADD COLUMN obj Object(JSON); -- 期望报错Object(JSON) 列只能在建表时声明3.4 修复创建 Kafka 表时 Kerberos 初始化异常导致的段错误发布说明Fix a segfault caused by a thrown exception in Kerberos initialization during the creation of the Kafka tablePR #56401关闭 issue #56073。问题现象当 Kafka 表引擎启用 Kerberos/GSSAPI 认证且环境配置不完整如缺少 keytab、kinit 失败时Kerberos 初始化抛出的异常在创建表的路径上未被安全捕获导致服务进程段错误segfault而非返回可读错误。源码佐证src/Storages/Kafka/KafkaConfigLoader.cpp 引入了Access/KerberosInit.h并在 L403-L409 处理kafka_sasl_mechanism/kafka_sasl_username/kafka_sasl_password等 SASL 配置L467 附近使用cppkafka::Configuration获取默认sasl.kerberos.kinit.cmd。从代码结构可以推断Kerberos 初始化发生在建表CREATE TABLE ... ENGINE Kafka的配置组装阶段异常的传播路径涉及 C 与 librdkafka 的边界。修复要点在 Kerberos 初始化入口补充异常边界使认证失败以标准异常Exception形式向上抛出由建表流程统一处理服务进程保持存活。这属于典型的异常安全exception safety缺陷修复——崩溃不再发生取而代之的是可诊断的错误信息。验证方式-- 在无有效 Kerberos 票据的环境下创建使用 GSSAPI 的 Kafka 表 CREATE TABLE k (msg String) ENGINE Kafka SETTINGS kafka_broker_list host:9092, kafka_sasl_mechanism GSSAPI, kafka_security_protocol SASL_PLAINTEXT; -- 修复后返回认证失败的错误信息服务不崩溃3.5 RabbitMQ 表引擎支持安全TLS连接发布说明Fixed the issue that the RabbitMQ table engine wasnt able to connect to RabbitMQ over a secure connectionPR #56703。问题现象此前 RabbitMQ 表引擎无法通过amqps://TLS端点建立连接仅支持明文amqp://无法满足生产环境传输加密需求。源码佐证连接建立路径在 src/Storages/RabbitMQ/RabbitMQConnection.cppAMQP::Address address(configuration.host, configuration.port, login, configuration.vhost, configuration.secure);secure标志最终传递给 AMQP-CPP 的Address构造函数其来源与校验逻辑位于 src/Storages/RabbitMQ/StorageRabbitMQ.cpp连接是否为 TLS 取决于rabbitmq_secure设置或地址形式使用rabbitmq_host_port形式时设rabbitmq_secure 1启用 TLS使用rabbitmq_address形式时传输层由 URI scheme 决定——应使用amqps://此时rabbitmq_secure被忽略若在明文amqp://地址上同时设置rabbitmq_secure 1本版本起直接拒绝建表而非静默降级为明文连接见 StorageRabbitMQ.cpp#L185-L189 的错误信息。对应设置定义在 src/Storages/RabbitMQ/RabbitMQSettings.cpp#L30DECLARE(Bool, rabbitmq_secure, false, Use SSL connection, 0)验证方式-- 形式一host/port rabbitmq_secure CREATE TABLE mq (id UInt64, payload String) ENGINE RabbitMQ SETTINGS rabbitmq_host_port broker.example.com:5671, rabbitmq_exchange_name events, rabbitmq_secure 1; -- 形式二amqps URI CREATE TABLE mq2 (id UInt64, payload String) ENGINE RabbitMQ SETTINGS rabbitmq_address amqps://guest:guestbroker.example.com/vhost, rabbitmq_exchange_name events;注意事项来自 StorageRabbitMQ.cpp 源码注释 L1637所依赖的 AMQP 库默认不校验TLS 证书链——证书过期、自签名、缺失或无效时连接依然被允许更严格的证书校验留待后续实现。生产环境如需双向认证与证书固定应在网络层如服务网格或代理另行处理。3.6 FPC 压缩编解码器解压损坏数据不再导致服务崩溃发布说明The server crashed when decompressing malformed data using theFPCcodecPR #56795该问题由 ClickHouse Bug Bounty Program 发现。问题现象当磁盘上的数据块使用FPC编解码器且内容被损坏截断、位翻转等时解压路径缺少边界校验越界读取导致服务器进程崩溃。这是典型的损坏输入导致内存安全问题缺陷。源码佐证src/Compression/CompressionCodecFPC.cpp 是 FPC 编解码器实现——其算法源自论文M. Burtscher, P. Ratanaworabhan: FPC: A high-speed compressor for double-precision floating-point data (2008)见 L19-L22 注释面向浮点时间序列数据使用 FCM/DFCM 双预测器FcmPredictor / DfcmPredictor对相邻浮点值进行差分预测。当前仓库中该文件包含多层防御性解压校验正是此类崩溃修复的落点头部校验L496-L497source_size HEADER_SIZE时抛CANNOT_DECOMPRESSlevel 校验L502-L503compressed_level为 0 或大于MAX_COMPRESSION_LEVEL28时抛异常float width 校验L507-L515仅接受 4/8 字节宽度否则抛异常码流边界校验decodePair L413-L433对每一对值检查zero byte count是否超过值宽度VALUE_SIZE、使用__builtin_add_overflow检测tail_size累加溢出并校验bytes.size() expected_size时抛 Unexpected end of encoded sequence。从代码结构可以推断崩溃的根因在于解压路径对畸形编码头如伪造的 zero-byte 计数缺乏长度约束修复通过上述逐层校验将越界读写转化为可恢复的CANNOT_DECOMPRESS异常并由查询层统一报告错误。验证方式-- FPC 是浮点专用 codec建表/压缩仍正常 CREATE TABLE f (t DateTime, v Float64 CODEC(FPC)) ENGINE MergeTree ORDER BY t; -- 若底层数据被损坏修复后查询返回解压错误而非使服务崩溃 -- DB::Exception: Cannot decompress FPC-encoded data. ...相关参数来自 registerCodecFPC参数默认值取值范围含义compression_level第 1 参121–28预测器哈希表大小 2^level × float_width字节float_width第 2 参按列类型4/84 或 8目标浮点宽度允许显式指定注意FPC仅适用于Float32/Float64类型列getFloatByteWidth L99-L108 对非浮点类型直接抛BAD_ARGUMENTS且被标记为isFloatingPointTimeSeriesCodec()L45即专为时序浮点数据设计。四、其余条目4.1 NO CL CATEGORYPR #56598Backported in #56601未标注 changelog 类别的内部修复内容未公开归类属于维护性改动。4.2 NOT FOR CHANGELOG / INSIGNIFICANT本版本还包含若干不面向用户输出的内部改动PR #56385将 CI 作业改写为可调用工作流callable workflowPR #56501继续将工作流迁移为可复用测试reusable testsPR #56854改进异常信息文本使错误消息更易诊断。这些改动与 ci 目录下的工作流体系ci/workflows直接相关对最终二进制行为无影响。五、升级与验证建议v23.8.7.24-lts 是 23.8 LTS 系列第 7 个补丁版本变更面小、无新功能、无破坏性语法变更适合作为生产环境的低风险升级候选。建议按以下顺序验证回归核心路径FPC 编解码浮点列读写、Kafka/RabbitMQ 表引擎建表与消费检查受影响的 SQL若业务中使用了view()UNION、表函数创建的表查询system.tables.data_paths确认结果行为符合预期验证安全配置RabbitMQ 若从明文迁移到 TLS确认amqps://或rabbitmq_secure 1配置生效同时留意当前版本不校验 TLS 证书链的限制异常注入测试对 FPC 编码的存储目录进行损坏数据模拟确认查询返回CANNOT_DECOMPRESS异常而非进程崩溃。完整的逐条发布记录可继续查阅 docs/changelogs/archive/v23.8.7.24-lts.md23.8 LTS 全系列变更见 docs/changelogs 目录相关实现源码位于 src/Compression/CompressionCodecFPC.cpp、src/TableFunctions/TableFunctionView.cpp、src/Storages/RabbitMQ、src/Storages/Kafka 与 src/Storages/System/StorageSystemTables.cpp。【免费下载链接】ClickHouseClickHouse® is a real-time analytics database management system项目地址: https://gitcode.com/GitHub_Trending/cli/ClickHouse创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进