ClickHouse v21.6.7.57-stable 补丁版本解析:pointInPolygon 校验开关与后台任务退避修复
发布时间:2026/9/12 17:52:07 作者:尧图编辑部 阅读量:1,286

ClickHouse v21.6.7.57-stable 补丁版本解析pointInPolygon 校验开关与后台任务退避修复【免费下载链接】ClickHouseClickHouse® is a real-time analytics database management system项目地址: https://gitcode.com/GitHub_Trending/cli/ClickHousev21.6.7.57-stable 是 ClickHouse 21.6 稳定分支上的一个维护性补丁版本它不引入新功能而是集中修复了ALTER MODIFY COLUMN与 TTL 表达式的交互、后台任务池满载时的退避异常、右子查询 JOIN 的线程估算以及pointInPolygon在关闭多边形校验时的崩溃风险。本文以仓库中的 v21.6.7.57-stable 变更日志 为骨架结合当前仓库源码逐条拆解每个修复背后的实现原理、触发场景与验证方法帮助你理解补丁版本到底修了什么、为什么这么修。版本基线FIXME 标记与 21.6 分支的维护节奏该变更日志标题写为ClickHouse release v21.6.7.57-stable FIXME as compared to v21.6.6.51-stable。其中FIXME是 ClickHouse 变更日志生成流程中常见的占位标记正式发布时该位置通常会被替换为与前一个版本的完整对比链接这里保留原样说明该文档是发布流程中的中间产物但其记录的修复内容本身是确定的。从版本号可以读出两条信息基线版本v21.6.7.57-stable 是 21.6 系列的第 7 个补丁版本对比对象是 v21.6.6.51-stable发布性质21.6 属于 ClickHouse 的 LTS长期支持稳定分支补丁版本只合入经过回归验证的 Bug Fix不会携带破坏性变更这也决定了本日志中所有条目都属于Bug Fix类别。修复一ALTER MODIFY COLUMN 与 TTL 表达式的兼容性问题问题现象第一个修复对应 PR #25554由 Anton Popov 提交FixALTER MODIFY COLUMNof columns, which participates in TTL expressions.即当某列参与了表的 TTL 表达式行级 TTL、列级 TTL 或 TTL 用于删除/移动数据时对该列执行ALTER MODIFY COLUMN修改列类型或参数会触发问题。TTL 表达式会被持久化在表元数据中并在后台合并merge任务执行时被重新解析求值若列定义被修改而 TTL 表达式未同步重写就会导致元数据解析失败或行为不一致。实现原理在 MergeTree 家族引擎中TTL 信息MergeTreeData::TTLInfo、TTLDescription以及由 TTL 派生出的表达式例如TTL_datetime INTERVAL 1 DAY是随表结构一起存储的。ALTER MODIFY COLUMN通过InterpreterAlterQuery进入MergeTreeData::alterTable流程系统需要同时更新列定义与所有依赖该列的 TTL 表达式。从当前仓库源码结构看这一修复的落点在元数据更新链路MergeTree 引擎的 alterTable 实现 负责校验列变更的兼容性而 TTL 表达式的校验与重建涉及 src/Storages/MergeTree/MergeTreeData.h 中 TTL 描述的解析逻辑。修复的核心是当列类型发生变化时重新解析并校验涉及该列的 TTL 表达式确保元数据中记录的 TTL 与新列定义保持自洽避免后台任务按旧元数据执行时出错。实际影响与建议如果业务中频繁使用ALTER TABLE ... MODIFY COLUMN调整列类型如将DateTime列扩容、修改String列的LowCardinality包装且该列同时出现在TTL子句中建议升级到该补丁版本升级后执行列类型变更时应同时在测试环境验证相关 TTL 仍能正常求值例如通过SELECT观察 TTL 列的值变化或触发一次 merge 观察后台任务日志。修复二后台任务池满载时的极长退避问题问题现象第二个修复对应 PR #25893alesapin修复 issue #25836Fix extremely long backoff for background tasks when the background pool is full.MergeTree 家族引擎依赖后台任务池BackgroundJobsExecutor执行 merge、mutation、分区删除TTL 触发的DELETE/MOVE等任务。当任务池满载达到background_pool_size/background_merges_mutations_concurrency_ratio配置的上限时新任务需要排队等待此前的实现会在任务反复失败或反复入队失败时计算指数退避backoff但在某些满载场景下退避时间会被计算得异常长导致原本应该尽快重试的任务被挂起过久表现为merge 长时间不推进大量分区堆积磁盘空间告警后 TTL 清理迟迟不执行。实现原理后台任务调度的核心位于 src/Storages/MergeTree/BackgroundJobsExecutor.cpp。该组件维护一张任务表task_storage周期性轮询所有表并挑选可执行的任务交给线程池。退避逻辑sleeptime/increaseSleepTime之类本意是当某张表的任务持续不可执行例如该表正在执行多个 merge 已达并发上限时降低对该表的轮询频率避免空转。修复前的缺陷在于当整个后台池满载时任务不可执行的原因不是该表有问题而是系统没有空闲线程此时仍按指数增长退避时间就会把系统繁忙误判为该表故障把睡眠时间推到数十分钟甚至更久。修复方向是区分表自身不可执行与全局线程不足两种状态在全局繁忙时避免指数放大退避间隔。相关配置background_pool_size后台任务池线程数上限默认 16background_merges_mutations_concurrency_ratiomerge/mutation 任务在线程池中的占比默认 0.5即一半线程用于 merge/mutationbackground_schedule_pool_size等与调度相关的线程配置。当系统出现merge 停滞 后台日志长时间无输出时除了排查退避问题还应检查这些配置是否被调得过小。修复三右子查询 JOIN 的线程数估算错误问题现象第三个修复对应 PR #26052Vladimir C关闭 issue #24075Fix wrong thread estimation for right subquery join in some cases.即在RIGHT JOIN或RIGHT ANY JOIN场景下当右表是子查询时查询计划对右子查询需要多少线程的估算在部分场景下是错误的可能引发资源浪费或调度失衡。实现原理从源码结构看JOIN 的线程规划在查询流水线构建阶段完成Join相关类位于 src/Interpreters/Join而每个 Join 步骤分配多少线程取决于QueryPlan中各节点的updateProgress与并行度degree计算。右连接RightJoin在语义上要求以右表为驱动表其子查询的输出行数、过滤选择性直接影响整体并行度分配当右子查询带有聚合、LIMIT或复杂过滤时行数估算偏差会被放大导致线程分配过多或过少。修复的核心是修正右子查询场景下的行数/线程估算路径使得流水线的并行度与实际数据量匹配。这在当前代码中对应QueryPipeline构建时对JoinStep的 degree 决策逻辑参见 src/Processors/QueryPlan 与 src/QueryPipeline。影响场景高频使用RIGHT JOIN (SELECT ...) AS r ON ...的分析查询右子查询本身包含聚合或高选择性过滤需要稳定的执行计划与线程利用率。如果你在 21.6.x 上观察到右连接查询偶发执行缓慢或 CPU 使用异常可关注本修复。修复四pointInPolygon 关闭校验后的崩溃风险问题现象第四个修复对应 PR #26113Alexey MilovidovFix possible crash inpointInPolygonif the settingvalidate_polygonsis turned off.即当服务器/会话设置validate_polygons 0时pointInPolygon函数在特定输入下存在崩溃风险。该修复是本次日志中唯一附带了完整底层实现可考证的条目下面结合当前仓库源码深入展开。pointInPolygon 是什么pointInPolygon是 ClickHouse 的地理/几何函数族Geo 类别之一用于判断平面上的点是否位于多边形内部返回UInt81表示在内部0表示不在。其注册与完整文档位于 src/Functions/pointInPolygon.cpp支持四种调用形式见源码getReturnTypeImpl中的注释-- 简单多边形无洞 pointInPolygon((x, y), [(x1, y1), (x2, y2), ...]) -- 带洞多边形每个洞作为后续独立参数 pointInPolygon((x, y), [(x1, y1), ...], [(h1x, h1y), ...], ...) -- 带洞多边形所有环合并为一个二维数组 pointInPolygon((x, y), [[(x1, y1), ...], [(h1x, h1y), ...], ...]) -- 多多边形MultiPolygon三维数组或逐参数传入 pointInPolygon((x, y), [[[...], ...], ...])参数要求第一个参数是(x, y)坐标元组多边形参数必须是数值元组的嵌套数组坐标内部会统一转换为Float64CoordinateType Float64参与计算。validate_polygons 设置的作用validate_polygons是一个会话级布尔设置默认值为true其定义位于 src/Core/Settings.cpp#L53630— 关闭校验pointInPolygon接受无效多边形可能返回不正确的结果1默认— 开启校验遇到自相交、自相切的多边形时抛出异常。在函数实现中src/Functions/pointInPolygon.cpp该设置通过FunctionPointInPolygon::create读取context-getSettingsRef()[Setting::validate_polygons]传入构造函数并存储为成员bool validate。当多边形为常量参数时parseConstPolygon/parseConstMultiPolygon在解析后会调用 boost.geometry 的bg::is_valid做完整性校验validate为true时校验失败会抛出BAD_ARGUMENTS异常见 pointInPolygon.cpp 的 parseConstPolygon。v21.6.7.57 之前的缺陷是关闭校验后某些畸形输入例如环顶点过少、坐标值溢出、退化几何会直接进入后续的网格grid预处理或 R-tree 匹配流程在无保护的前提下触发未定义行为乃至崩溃。崩溃修复与两条执行路径源码清晰展示了pointInPolygon的两类执行路径常量多边形路径预处理 缓存当多边形是常量poly_is_const时会被预处理器PointInPolygonWithGridF64/PointInMultiPolygonRTreeWithGrid转成网格/R-tree 结构以加速匹配预处理结果按常量参数的 XXH3 哈希hashConstPolygonArguments缓存在PreprocessedPolygonsCache中缓存上限由服务器设置point_in_polygon_cache_size控制默认 256 MiB见 src/Core/Defines.h#L137 与 src/Core/ServerSettings.cpp#L751。解析与校验只发生在缓存未命中时因此validate_polygons标志也被纳入缓存键避免用关闭校验时构建的条目满足开启校验的查询非常量多边形路径逐行射线法当多边形来自表列时使用 W. Randolph Franklin 的射线投射pnpoly算法逐行判定见isInsideRing的实现注释与代码src/Functions/pointInPolygon.cpp#L565-L629。该算法对顶点数小于 2 的环直接返回false并在解析常量环时通过common::mulOverflow检查坐标乘积溢出。v21.6.7.57 的修复要点从源码可以确认在validate_polygons 0时确保进入预处理流程的几何仍然满足基本的结构约束至少 3 个顶点、坐标可参与后续计算从而封堵崩溃路径。验证与测试用例仓库中pointInPolygon的无状态测试覆盖了上述两类路径与各种几何形态tests/queries/0_stateless/00500_point_in_polygon.sql —— 覆盖简单多边形、带洞多边形、多多边形、逆序顶点、自相交多边形默认校验下期望BAD_ARGUMENTS异常、常量/非常量多边形混合等场景对应的期望输出 tests/queries/0_stateless/00500_point_in_polygon.reference 中包含了 inner/outer、polygon with holes、polygons with reversed direction、multipolygon with one/two polygons with holes 等测试分组的结果更多常量化测试见 tests/queries/0_stateless/00500_point_in_polygon_2d_const.sql。可以通过如下方式复现默认行为关闭校验前后的差异-- 默认 validate_polygons 1自相交多边形会抛 BAD_ARGUMENTS SELECT pointInPolygon((0.1, 0.1), [(0.5, 0.), (1.0, 0.), (8.0, 7.5), (7.5, 8.0), (0., 1.), (0., 0.5), (4.5, 5.5), (5.5, 4.5), (0.5, 0.)]); -- 关闭校验后不会抛异常但结果可能不正确 SET validate_polygons 0; SELECT pointInPolygon((0.1, 0.1), [(0.5, 0.), (1.0, 0.), (8.0, 7.5), (7.5, 8.0), (0., 1.), (0., 0.5), (4.5, 5.5), (5.5, 4.5), (0.5, 0.)]);运维建议除非有明确的性能诉求且数据源保证多边形合法否则建议保持validate_polygons 1默认值以让非法几何在查询期被显式拒绝而不是得到不确定结果若因历史数据原因必须关闭校验请升级到包含 v21.6.7.57或更新稳定版的版本避免触发此崩溃路径涉及大量常量多边形的查询可关注point_in_polygon_cache_size服务器设置可在运行时修改并立即生效并可用SYSTEM DROP POINT IN POLYGON CACHE手动清空缓存而不改变大小上限。NOT FOR CHANGELOG 条目21.6 手动回移植日志末尾有一条NOT FOR CHANGELOG / INSIGNIFICANT条目21.6 manual backport of #25970 #26138这是将主分支master上的 PR #26138 手动回移植到 21.6 分支的说明。在 ClickHouse 的发布流程中凡是进入稳定分支的改动都必须经过backport流程自动化或手动标记为 NOT FOR CHANGELOG 表示该改动属于内部流程性质如构建/测试基础设施修复不会对用户可见行为产生直接影响因此不进入正式变更日志正文。总结与升级建议v21.6.7.57-stable 是一个小而准的稳定分支补丁四个 Bug Fix 分别落在修复涉及模块对用户的影响ALTER MODIFY COLUMN 与 TTL 列交互MergeTree 元数据MergeTreeData.cpp避免修改 TTL 列类型时元数据不一致后台任务池满载的极长退避后台调度BackgroundJobsExecutor.cpp避免 merge/清理任务长时间停滞RIGHT JOIN 子查询线程估算查询计划/流水线src/Processors/QueryPlan右连接查询的线程分配更准确pointInPolygon 关闭校验崩溃几何函数pointInPolygon.cpp封堵畸形多边形输入下的崩溃路径如果你正在使用 21.6 LTS 分支且业务涉及 TTL 列变更、后台任务压力较大、右连接分析或地理围栏类查询pointInPolygon建议优先升级到该版本或更新的 21.6.x 补丁。升级前请在测试环境回归上述场景特别是validate_polygons 0的存量查询。【免费下载链接】ClickHouseClickHouse® is a real-time analytics database management system项目地址: https://gitcode.com/GitHub_Trending/cli/ClickHouse创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考