
深度解析 ClickHouse v23.2.3.17-stable 发布五个回移缺陷修复及其源码原理【免费下载链接】ClickHouseClickHouse® is a real-time analytics database management system项目地址: https://gitcode.com/GitHub_Trending/cli/ClickHouse本文以 ClickHouse 2023.2 LTS 分支的补丁版本 v23.2.3.17-stable构建提交 dec18bf7281对比基线 v23.2.2.20-stable / f6c269c8df2为对象逐条解读其官方变更日志中记录的 5 个用户可见缺陷修复与 3 个内部改进并结合当前仓库中对应模块的源码实现说明每项修复背后的机制与影响面。读完本篇你可以掌握ClickHouse 23.2 分支的 backport 发布模式、查询规范化器QueryNormalizer的别名递归问题、GROUP BY 键聚合函数优化规则、maxIntersections 空间聚合函数的内存问题、systemd 服务文件排错以及 PREWHERE 具体列支持的边界。1. 版本概览LTS 分支的回移Backport发布v23.2.3.17-stable 不是功能版本而是针对 23.2 系列稳定线的增量补丁。变更日志 docs/changelogs/archive/v23.2.3.17-stable.md 的标题行明确了两个坐标ClickHouse release v23.2.3.17-stable (dec18bf7281) FIXME as compared to v23.2.2.20-stable (f6c269c8df2)其发布模式有两条典型特征从日志的条目格式即可看出双编号引用每条修复都写作 Backported in #46907 ... [#46609]即先在主干master合入原始修复 PR再通过一个独立的 backport PR 回移到 23.2 发布分支。原始 PR 决定修什么backport PR 决定进入哪个分支。FIXME 标记标题中的FIXME as compared to表示该对比范围是补丁基线日志只收录基线之后的增量变更而非该版本的全部历史。本次共包含 5 条Bug Fix (user-visible misbehavior in official stable release)条目和 3 条NOT FOR CHANGELOG / INSIGNIFICANT条目。下面逐条展开。2. Bug Fix 条目详解2.1 修复 QueryNormalizer 中错误的别名递归PR #46609backport #46907Raúl Marín日志原文Fix incorrect alias recursion in QueryNormalizer.QueryNormalizer 是 ClickHouse 在解释查询前对 AST 做规范化的组件它依据表的 alias 定义与列别名把引用别名的表达式展开为实际表达式并提取查询参数。别名展开天然是递归过程——若别名链形成环例如a AS b、b AS a这类循环引用没有环检测的展开就会无限递归。从当前仓库的源码结构可以印证这一机制的设计。QueryNormalizer 头文件 中Data结构维护了三组状态用于遍历与去环MapOfASTs finished_asts; /// already processed vertices (and by what they replaced) SetOfASTs current_asts; /// vertices in the current call stack of this method std::string current_alias; /// the alias referencing to the ancestor of ast (the deepest ancestor with aliases)current_asts记录当前调用栈上的 AST 顶点finished_asts记录已处理顶点及其替换结果——这正是处理别名递归/循环引用所需的两类状态一旦在展开过程中再次遇到当前调用栈上的节点即可判定循环并中止。仓库中还配有专门测试这一类场景的用例 gtest_cycle_aliases.cpp以及依赖该组件的调用点如 QueryNormalizer.cpp、TreeRewriter.cpp。可以推断v23.2 中该缺陷的触发面是在包含递归别名的查询上规范化过程要么无限递归导致栈溢出/卡死要么产生错误的展开结果。修复PR #46609使递归终止条件正确。对于依赖视图/物化视图、存储过程式 SQL 函数或 prepared 查询模板的用户这条修复直接关系循环别名是否会被安全拒绝或正确展开的边界行为。2.2 修复含 min/max 的聚合优化中的算术运算PR #46705backport #47091Duc Canh Le日志原文Fix arithmetic operations in aggregate optimization withminandmax.ClickHouse 有一条经典优化规则当表达式中的列出现在GROUP BY键中时该列在组内是常量min(x)与max(x)都可以直接替换为x。例如SELECT min(k) max(v) FROM t GROUP BY k可等价改写为SELECT k max(v) FROM t GROUP BY k。该优化由 TreeOptimizer.cpp 中的optimizeAggregateFunctionsOfGroupByKeys驱动void optimizeAggregateFunctionsOfGroupByKeys(ASTSelectQuery * select_query, ASTPtr node) { if (!select_query-groupBy()) return; const auto group_by_keys select_query-groupBy()-children; GroupByKeysInfo group_by_keys_data getGroupByKeysInfo(group_by_keys); SelectAggregateFunctionOfGroupByKeysVisitor::Data visitor_data{group_by_keys_data.key_names}; SelectAggregateFunctionOfGroupByKeysVisitor(visitor_data).visit(node); }其中getGroupByKeysInfo解析出 GROUP BY 键含列名/别名/表达式形态再交给 AggregateFunctionOfGroupByKeysVisitor.h 中的访问器沿 SELECT 列表做自底向上替换。这条优化要求替换过程必须正确穿透算术表达式只有当min(x)、max(x)作为加减乘除等二元运算的子节点时也应当能被识别并替换同时不能把不属于 GROUP BY 键的聚合误替换。从日志条目表述可以推断23.2 版本的缺陷正是出现在聚合函数嵌套在算术表达式内部这一形态——替换逻辑对算术子树处理不正确可能产生错误的查询改写进而影响查询结果正确性。这对所有使用GROUP BY且 SELECT 中含min(...)/max(...)参与算术运算的分析查询都是潜在正确性风险属于必须升级到 23.2.3.17 的一类修复。2.3 修复 maxIntersections 函数中的 MSan 报告PR #46847backport #46885Alexey Milovidov日志原文Fix MSan report in themaxIntersectionsfunction. This closes #43126.maxIntersections是 ClickHouse 用于空间数据的聚合函数计算与查询矩形相交次数最多的几何集合常配合RectAngular2D、Point等几何类型使用。MSanMemorySanitizer是 Clang 提供的未初始化内存检测器其报告意味着函数内部存在读取未初始化内存的路径——这类问题不一定立刻崩溃但会导致不可复现的错误结果或性能问题。从 AggregateFunctionMaxIntersections.cpp 的实现可以看到该函数的结构特点也解释了为何容易触碰未初始化内存MaxIntersectionsDataPointType作为聚合状态内部采用基于 Arena 的分配器源码注释标明 MaxIntersectionsData::Allocator uses the arena并通过static_assert(offsetof(...Value, first) 0)对状态内存布局做硬校验该文件的布局断言聚合类型按AggregateFunctionIntersectionsKindCount / Position 等注册为maxIntersections、positionOfMaxIntersections等多个函数名注册逻辑。这类按位/按偏移手工管理布局的聚合状态在新增相交点、扩容等路径上若遗漏对填充区的初始化就会被 MSan 捕获。此修复关闭了自 2022 年即被追踪的问题 #43126空间数据GIS用户应升级到本版本以消除未初始化读取。2.4 修复 systemd 服务文件拼写错误导致服务启动失败PR #47051backport #47067Palash Goel日志原文Fix typo in systemd service, which causes the systemd service start to fail.ClickHouse 的发行版打包单元.deb/.rpm自带 systemd 服务文件 clickhouse-server.service。该文件在[Unit]段声明了DescriptionClickHouse Server (analytic DBMS for big data)、Aftertime-sync.target network-online.target等依赖在[Service]段使用Typenotify、Restartalways、RestartSec30等配置。service 文件是强解析的 INI 格式——任何一个键名拼写错误或非法行都可能导致 systemd 解析失败从而systemctl start clickhouse-server直接报错服务器起不来。从当前仓库的 service 文件可以看到修复后的规范形态包括环境变量文件声明EnvironmentFile-/etc/default/%p # Bring back /etc/default/clickhouse for backward compatibility EnvironmentFile-/etc/default/clickhouse见 clickhouse-server.service-前缀表示文件不存在时不报错即/etc/default/clickhouse是可选的。packages/clickhouse-server.postinstall同样在包安装阶段兼容性地加载该文件[ -f /etc/default/clickhouse ] . /etc/default/clickhouse。对于使用官方 tarball 之外、走包管理器部署的用户这条修复保证了服务单元可被 systemd 正常解析与拉起。2.5 修复具体列的 PREWHERE 支持PR #47154backport #47259Azat Khuzhin日志原文Fix concrete columns PREWHERE support.PREWHERE 是 ClickHouse 特有的列式预过滤子句SELECT ... FROM t PREWHERE 过滤条件 WHERE 其余条件。它的价值在于列存储引擎按列读取的特性——PREWHERE 条件只涉及少数列时引擎先读取并过滤这些列、确定幸存的行号集合再按该集合去读其他列从而显著减少 I/O 与计算量。concrete columns PREWHERE 指的是 PREWHERE 条件中显式引用具体列相对更宽泛的表达式形态的支持路径。可以推断23.2 中该路径存在实现缺口或错误PREWHERE 被改写/执行时对具体列的处理不正确可能退化为非预期行为或报错。本条目修复使这一列式预过滤能力在覆盖具体列引用的查询形态下恢复可用。对于依赖 PREWHERE 优化大表点查/区间扫描的负载本版本的行为与更高版本对齐。当前仓库中 PREWHERE 相关实现大量存在于查询计划与存储读取层例如src/Processors下的列式读取路径23.2 时代的代码组织虽与当前主干有差异但先过滤、后按行号取列的核心机制一致。3. NOT FOR CHANGELOG / INSIGNIFICANT 条目日志将以下三项归为不进正式变更说明的内部改进但它们对运维有实际参考价值systemd 也使用 /etc/default/clickhousePR #47003Mikhail f. Shiryaev此前/etc/default/clickhouseSysV init 风格的环境变量文件见 clickhouse-server.init 中CLICKHOUSE_STOP_TIMEOUT等约定只在 init 脚本路径生效本改进让 systemd 服务同样通过EnvironmentFile-/etc/default/clickhouse读取它见 clickhouse-server.service。这消除了init 与 systemd 两种部署方式环境变量行为不一致的坑运维可以统一在/etc/default/clickhouse中放置诸如停止超时等配置。上下文切换时执行 flushUntrackedMemoryPR #47102Sema ChecherindaClickHouse 的内存池会跟踪未跟踪内存untracked memory即绕过池直接分配的内存并在特定时机刷新统计。将刷新时机与上下文切换context switches事件挂钩可以推断其目的是让内存统计与系统调度事件同步使system.metrics、内存剖析等观测数据更及时地反映真实占用——这对排查内存峰值与 OOM 边界问题有帮助。更新 PyGithub 新版本的类型标注PR #47123Mikhail f. Shiryaev纯 CI 工具链维护属于 Python 侧类型注解随依赖版本升级的适配不影响数据库运行行为。4. 适用前提与升级建议适用对象运行在 23.2 稳定线如 v23.2.2.x且通过包管理器或 tarball 部署的用户。本版本是纯缺陷修复版本不包含新特性升级风险低、收益是 5 项行为修正。优先关注查询正确性风险最高的是 2.2min/max 聚合优化的算术表达式改写错误——若你的分析查询含GROUP BY且 SELECT 中min()/max()参与算术运算应尽快升级通过 systemd 拉起服务且遇到过service start to fail的用户对应 2.4使用 GIS 空间聚合maxIntersections系列与 PREWHERE 优化的负载分别对应 2.3 与 2.5。验证方式升级后可用SELECT version()确认版本号为23.2.3.17或更高补丁号systemd 部署可执行systemctl status clickhouse-server确认服务解析正常针对聚合优化行为可用含GROUP BYmin/max算术表达式的对照查询验证结果一致性。版本边界说明本文引用的源码文件src/Interpreters/QueryNormalizer.h、src/Interpreters/TreeOptimizer.cpp等来自当前仓库的较新代码结构用于说明这些机制的实现原理23.2 分支自身代码的组织细节可能有所不同具体以该发布分支为准。变更日志体系ClickHouse 每个稳定版本的变更日志均按本文档同款结构版本对比标题、Bug Fix、Feature、Improvement、NOT FOR CHANGELOG 等分区存放于 docs/changelogs 目录可按同一模式查阅其它版本。5. 小结v23.2.3.17-stable 用一个紧凑的补丁集合展示了 ClickHouse 23.2 LTS 分支的维护方式主干修复#46609、#46705、#46847、#47051、#47154经由独立 backport PR 回移覆盖查询规范化递归安全、聚合改写正确性、空间聚合内存安全、服务部署可靠性和 PREWHERE 列式预过滤五条线。结合仓库源码可以看到这些修复点分别落在查询 AST 规范化QueryNormalizer.h、查询树优化TreeOptimizer.cpp、聚合函数实现AggregateFunctionMaxIntersections.cpp与部署单元clickhouse-server.service等模块——对维护 23.2 生产集群的团队本版本是低成本、高确定性的升级目标。【免费下载链接】ClickHouseClickHouse® is a real-time analytics database management system项目地址: https://gitcode.com/GitHub_Trending/cli/ClickHouse创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考