ARTICLE · INTELLIGENCE

战地情报 · 详情页

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

ClickHouse v22.10.6.3-stable 补丁解读:修复 Wide Part 轻量删除掩码下 ALTER TABLE TTL 报错

ClickHouse v22.10.6.3-stable 补丁解读:修复 Wide Part 轻量删除掩码下 ALTER TABLE TTL 报错 ClickHouse v22.10.6.3-stable 补丁解读修复 Wide Part 轻量删除掩码下 ALTER TABLE TTL 报错【免费下载链接】ClickHouseClickHouse® is a real-time analytics database management system项目地址: https://gitcode.com/GitHub_Trending/cli/ClickHouse本篇文章围绕 ClickHouse 官方稳定版v22.10.6.3-stable的唯一一条用户可见 Bug Fix 展开剖析Wide 格式数据分片part携带轻量删除掩码lightweight delete mask时执行ALTER TABLE ... MODIFY TTL会报错这一问题的成因、修复边界与升级建议。读完本文你将理解 ClickHouse 轻量删除与 TTL 两条核心机制在 MergeTree 存储引擎中的底层交互并掌握如何规避与验证该历史缺陷。版本概览一条关键 Bug Fix 的补丁版本该 changelog 位于 docs/changelogs/archive/v22.10.6.3-stable.md记录了 ClickHouse 官方稳定发布版本v22.10.6.3-stable提交645a66d221f相对上一稳定版v22.10.5.54-stable提交dbc7984dc3b的变更。该版本仅包含一条变更归类为Bug Fix (user-visible misbehavior in official stable release)即官方稳定版中用户可见的异常行为修复修复当 Wide part 带有轻量删除掩码时ALTER TABLE TTL报错的问题PR [#44959]作者 Mingliang Pan。从变更组织方式可以看到 ClickHouse 的补丁发布策略补丁版本patch release只回填backported被官方判定为用户可见异常的修复不引入新功能以保障生产环境的稳定性。因此这个版本的意义不在于功能增量而在于消除一个特定数据布局下的 ALTER 故障点。修复内容详解Wide Part 轻量删除掩码 TTL 三者的碰撞该修复针对的核心场景是数据表使用 MergeTree 系列引擎表中的部分数据分片以Wide 格式存储每列一个独立文件区别于 Compact 格式的列合并存储这些分片此前执行过轻量删除lightweight delete因此分片内存在轻量删除掩码标记被删除的行此时对表执行ALTER TABLE ... MODIFY TTL或涉及 TTL 的ALTER操作会抛出错误。修复前TTL 相关的 ALTER 在遍历分片元数据、计算行数与过期行时未能正确处理带删除掩码的 Wide part导致操作失败修复后TTL 的 ALTER 流程可以正确识别并兼容这类分片。需要强调的是这条修复针对的是ALTER元数据变更路径中的兼容性问题。TTL 的实际执行在后台 merge 时根据 TTL 表达式删除过期数据与轻量删除的合并逻辑是相对独立的但任何涉及 TTL 元数据变更的操作都必须能够安全地与轻量删除状态共存——这正是本次补丁所保障的。前置概念一ClickHouse 轻量删除Lightweight Delete的实现机制要理解该 Bug需要先了解轻量删除在 MergeTree 引擎中的落地方式。从源码看轻量删除并非物理抹除数据行而是通过一个隐藏列与删除掩码文件协作完成隐藏列_row_exists在 src/Storages/MergeTree/MergeTreeVirtualColumns.cpp 中定义了RowExistsColumn::name _row_exists。源码注释明确指出DELETE FROM语句会被重写为_row_exists 0的更新并且只有该精确字面量才算删除任何其他表达式例如试图用_row_exists 1复活行都会被当作对删除掩码的真实更新。删除掩码文件执行轻量删除后分片内会生成 lightweight delete mask 文件标识哪些行处于已删除状态。在 src/Storages/MergeTree/IMergeTreeDataPart.h 中可以找到相关接口如该 part 是否支持 lightweight delete mutatepart 中是否存在 lightweight delete mask 文件从_row_exists列读取现存行数等。行数语义变化同文件IMergeTreeDataPart.h中的注释表明rows_count这类统计量在带轻量删除的分片上表示排除被轻量删除行后的现存行数。也就是说轻量删除后的分片在磁盘布局、行数统计、虚拟列语义上都与普通分片存在差异任何遍历分片的操作包括 TTL 相关 ALTER都必须感知这些差异否则就会像本 Bug 一样在特定条件下报错。前置概念二TTL 与 ALTER TABLE TTL 的执行路径ClickHouse 的 TTL 能力分为两类表级 TTLTable TTL对满足条件的整行进行过期删除DELETE、移动到其他磁盘/卷TO DISK / TO VOLUME或重压缩RECOMPRESS列级 TTLColumn TTL仅对指定列在过期后重置值。ALTER TABLE ... MODIFY TTL属于表元数据变更。在 src/Storages/MergeTree/MergeTreeData.cpp 的checkTTLExpressions中ClickHouse 会对新旧 TTL 表达式做合法性校验例如禁止对主键/排序键列设置列级 TTL、校验TO DISK/TO VOLUME目标是否存在等该校验位于ALTER提交前是防止错误元数据写入的关键防线。而在 TTL 的实际执行侧过期数据主要在后台 merge 时被清除。从 src/Storages/MergeTree/MergeTask.h 的 Merge 运行时上下文可以看到相关字段设计vertical_lightweight_delete与vertical_ttl_delete分别标记垂直合并阶段是否处理轻量删除 / TTL 删除ttl_drop_short_circuit当所有源分片完全过期MergeType::TTLDrop时直接短路——不打开 reader、不分配缓冲产出空分片merging_columns_expired_by_ttl/storage_columns_expired_by_ttl记录参与合并的、被 TTL 标记过期的列input_rows_filtered注释明确指出若存在轻量删除掩码则部分输入行在读取后立即被过滤。这些字段表明在数据合并层面 TTL 与轻量删除已经被设计为可协同工作本次修复补上的是ALTER 元数据变更层的这一环。问题根因分析基于源码推断结合上述机制可以从源码结构推断出该 Bug 的成因链条Wide part 执行轻量删除后分片内存在删除掩码且分片的现存行数等统计量语义发生变化排除已删除行对表执行ALTER TABLE ... MODIFY TTL时ALTER 流程需要加载分片元数据、评估现有分片对新 TTL 元数据的兼容性并可能触发 TTL 相关的重算或校验在 v22.10.6.3 之前的版本中该 ALTER 路径未对Wide part 轻量删除掩码的组合做特判导致解析或元数据读取阶段抛错即 changelog 中描述的alter table ttl error修复PR #44959在 ALTER/TTL 处理逻辑中补齐了对轻量删除掩码的兼容处理使带删除掩码的 Wide part 可以正常参与 TTL 元数据变更。需要说明的是以上为基于当前仓库源码结构的推断由于该修复发生于较老版本线现行主干代码src/Storages/MergeTree/AlterConversions.h 中的hasLightweightDelete()、hasDeleteMutation()等接口已演进为更完整的轻量删除兼容体系包括读取时按apply_deleted_mask决定是否应用删除掩码等能力。影响范围、升级建议与验证方式影响范围受影响版本v22.10.6.3-stable 之前、已支持轻量删除的 22.x 稳定版轻量删除自 21.x 引入22.x 已广泛使用受影响场景存在 Wide 格式分片、且这些分片执行过DELETE FROM轻量删除的 MergeTree 系列表对该表执行ALTER TABLE ... MODIFY TTL或相关 TTL 变更时可能报错不受影响场景纯INSERT/SELECT流量、无 TTL 变更的常规 DDL以及无轻量删除历史的分片。升级与规避建议升级生产环境若命中该场景应升级到v22.10.6.3-stable或任意更新的稳定版本临时规避在升级前若必须修改 TTL可先对受影响表执行一次OPTIMIZE TABLE ... FINAL触发 merge将轻量删除掩码在合并中物化被删除行物理清除使分片不再携带删除掩码后再执行ALTER TABLE ... MODIFY TTL该操作会带来额外的 I/O 与合并开销需在业务低峰期执行变更前备份任何 TTL 元数据变更都建议先在测试环境用含历史删除数据的分片复现验证。验证修复是否生效升级后可执行如下步骤快速验证以 MergeTree 表为例-- 1. 建表并插入数据 CREATE TABLE ttl_ld_test (id UInt32, ts DateTime) ENGINE MergeTree ORDER BY id TTL ts INTERVAL 1 MONTH; INSERT INTO ttl_ld_test SELECT number, now() FROM numbers(1000); -- 2. 执行轻量删除使分片带上删除掩码 DELETE FROM ttl_ld_test WHERE id % 2 0; -- 3. 触发部分分片转为 Wide 格式或将 min_bytes_for_wide_part 调小以生成 Wide part OPTIMIZE TABLE ttl_ld_test FINAL; -- 4. 修改表级 TTL修复前的报错场景 ALTER TABLE ttl_ld_test MODIFY TTL ts INTERVAL 2 MONTH; -- 5. 查询确认元数据已更新 SELECT name, value FROM system.merge_tree_settings WHERE name default_ttl_overwrite LIMIT 0; SELECT * FROM system.tables WHERE name ttl_ld_test FORMAT Vertical;在修复后的版本中第 4 步应正常返回若在旧版本复现则会抛出与 TTL/part 元数据相关的异常。总结v22.10.6.3-stable是一个典型的单点修复补丁版本但其价值不容小觑它补齐了Wide 格式分片 轻量删除掩码 TTL ALTER这一组合下的兼容性缺口让混合使用轻量删除与 TTL 运维操作的生产表不再一改 TTL 就报错。理解这条修复也等于掌握了 ClickHouse 存储引擎中删除与过期两类数据生命周期的底层分工——轻量删除以_row_exists/删除掩码做逻辑标记参见 MergeTreeVirtualColumns.cppTTL 在 merge 阶段以分片为单位物理清理参见 MergeTask.h二者既有分工又必须相互兼容。对于仍在 22.x 稳定线、且频繁使用DELETE FROM与 TTL 组合运维的用户建议尽快将版本推进至包含此修复的发布线。【免费下载链接】ClickHouseClickHouse® is a real-time analytics database management system项目地址: https://gitcode.com/GitHub_Trending/cli/ClickHouse创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

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