ClickHouse v26.3.11.36-lts 版本更新解析:从新设置到安全修复的完整技术指南
【免费下载链接】ClickHouseClickHouse® is a real-time analytics database management system项目地址: https://gitcode.com/GitHub_Trending/cli/ClickHouse
导读
本文基于 ClickHouse 官方 changelog 文档 docs/changelogs/v26.3.11.36-lts.md,系统梳理 v26.3.11.36-lts 这一维护版本(LTS 分支第 11 个补丁)的全部更新内容。文章覆盖 4 项功能改进、22 项用户可见的 Bug 修复、1 项构建/测试改进,并深入结合 src/Core/Settings.cpp 等仓库源码,详解新增设置defer_partition_pruning_after_final的语义与适用场景、SQL 注入漏洞的修复原理、以及多个崩溃类问题的根因。读完本文,你将掌握该版本的升级评估要点、受影响功能的排查方法,以及如何利用新增设置调优FINAL查询性能。
版本概览与升级背景
v26.3.11.36-lts 是 ClickHouse 26.3 LTS 分支上的第 11 个补丁版本,基线为 fa3aa24e791,上一版本为 v26.3.10.62-lts (e1c11930c28)。作为一个 LTS 维护版本,它不引入新功能,而是聚焦于:
- 正确性修复:多个查询结果错误、崩溃(crash)、use-after-free、数据竞争问题;
- 安全性修复:一个可导致任意 SQL 注入的字典源漏洞;
- 性能与健壮性改进:
FINAL查询的优化选项、备份、Refreshable MV 的稳定性; - 向后兼容性修复:修复旧客户端插入时的协议兼容问题。
该版本的完整条目可在仓库的 CHANGELOG.md 及 docs/changelogs 目录下追溯。
核心功能改进(Improvement)
1. 新增设置defer_partition_pruning_after_final:为 FINAL 查询提供性能回归开关
这是本版本最重要的一项变更(PR #104705),它把一个 26.3 中静默引入的行为变更暴露为可配置项。
背景:从 26.3 开始,ClickHouse 的FINAL查询(用于 ReplacingMergeTree 等去重引擎)会默认跳过分区裁剪(partition pruning)。这是因为FINAL需要按主键去重,而相同主键的行可能分布在不同的分区中——如果先按分区裁剪掉某些分区,就可能把参与去重的行静默排除掉,导致去重不完整、结果错误。
新设置语义(定义于 src/Core/Settings.cpp):
| 值 | 行为 | 适用场景 |
|---|---|---|
1(默认) | 延迟分区裁剪到FINAL之后(correctness-safe,正确性安全) | 通用场景,保证去重结果正确 |
0 | 在FINAL之前进行分区裁剪(恢复 pre-26.3 行为) | 事件日志类负载:同一主键行不可能跨分区 |
性能收益:当表的分区键列不在排序键中,且WHERE条件过滤了分区列时,设置为0可以显著加快查询——因为可以在读取阶段就裁剪掉大量分区。这适用于事件日志表(分区列在插入时确定、之后不会变化)等场景。
兼容性联动:设置compatibility = '26.2'会自动将该设置翻转为0,恢复 pre-26.3 的行为。
从源码看,src/Core/SettingsChangesHistory.cpp 中记录了该设置的版本历史——它作为一个"行为变更回溯文档化"条目注册在 26.3 块下,使得compatibility = '26.2'能够正确还原被 26.3 破坏的既有行为。值得注意的是,该设置在源码注释中说明"仅影响分区键列不包含在排序键中的分区表;对于其他表,分区裁剪始终生效"(见 src/Core/Settings.cpp)。
2. 备份健壮性:Refreshable Materialized View 持续刷新时的备份决策
PR #103384 改进了备份的韧性:当 Refreshable Materialized Views 被持续刷新时,备份决策现在基于快照化(snapshotted)表的状态,而不是全局状态。这避免了备份过程中因视图刷新导致的状态不一致,提升了BACKUP操作的可靠性。
3.lowerUTF8/upperUTF8大数据集处理修复
PR #104229,这两个函数常被用作文本索引(text index)的预处理器(preprocessor),例如配合hasAnyTokens、hasPhrase等索引函数使用(见 src/Functions/hasPhrase.cpp)。
4. 行策略与 FINAL 的交互优化
PR #102884 对FINAL查询中的行级安全(row policy)处理做了优化:当行策略只依赖排序键列且是确定性的时,跳过在FINAL之后延迟应用行策略,并同时跳过由此被迫执行的PREWHERE延迟。这减少了冗余处理。相关设置apply_row_level_security_after_final在 src/Core/Settings.cpp 中有说明——当启用且行策略使用非排序键列时,PREWHERE也会被延迟以保持执行顺序正确。
Bug 修复详解(用户可见行为修复)
本版本共包含 22 项用户可见的 Bug 修复,按功能域分类如下。
查询结果正确性修复
| 修复项 | 影响 | 修复 PR |
|---|---|---|
| INNER JOIN 过滤器被错误下推到 outer join 的 ON 子句 | 查询结果错误 | #101504 |
| RIGHT ANY JOIN 在右表多行/块拆分时结果错误 | 查询结果错误(issue #99431) | #102064 |
optimize_inverse_dictionary_lookup边界情况 | 可能静默丢行或抑制异常(issues #103270、#103085) | #104133 |
| 投影(projection)与 UNION ALL 视图、窗口函数、别名列冲突 | NOT_FOUND_COLUMN_IN_BLOCK 等异常 | #104317 |
关于optimize_inverse_dictionary_lookup:该设置用于优化字典"反向查找"场景,本次修复了该优化在若干边界情况下可能静默丢弃数据行或吞掉异常的正确性问题,升级后相关查询的结果可能与旧版本不同(以修复后的正确结果为准)。
崩溃与内存安全修复(Crash / use-after-free)
| 修复项 | 根因 | 修复 PR |
|---|---|---|
| 内存数据库中 ALTER 崩溃 | 临时表执行 ALTER 时的生命周期问题 | #102360 |
AggregateFunction状态与整数相乘的 heap-use-after-free | 平方取幂循环中状态自合并,merge重分配内部存储时为未定义行为 | #103536 |
StorageKafka2的 use-after-free | Keeper 会话被替换时消费者仍持有临时 topic-partition 锁 | #103890 |
AvroConfluentRowInputFormat段错误 | use-after-free | #104751 |
FutureSetFromTuple::buildOrderedSetInplaceTOCTOU 数据竞争 | 导致逻辑错误(logical error) | #104673 |
其中AggregateFunction乘法修复针对的是quantilesExactState(...) * N这类表达式——当聚合函数状态的merge会重分配内部存储时,指数平方循环中"状态与自身合并"是未定义行为,可能导致堆释放后使用。
字典源修复(含 SQL 注入漏洞)
关键安全修复(PR #104009):PostgreSQL、Cassandra 和 XDBC 字典源存在 SQL 注入漏洞——当字符串键包含单引号时,ExternalQueryBuilder使用\'(反斜杠)转义,但这些后端将反斜杠视为字面字符而非转义序列,从而允许任意 SQL 注入到字典查找查询中。修复后,这些后端改用 SQL 标准的''转义;ClickHouse 和 MySQL 字典源继续使用反斜杠转义。
从源码验证:在 src/Dictionaries/ExternalQueryBuilder.cpp 中,通过format_settings.values.escape_quote_with_quote = true;启用 SQL 标准引号转义(''),注释明确说明"SQL-standard DBs (PostgreSQL, Cassandra, etc.) treat\as a literal character, so use''escaping"。该构建器被 src/Dictionaries/PostgreSQLDictionarySource.cpp、src/Dictionaries/CassandraDictionarySource.cpp、src/Dictionaries/XDBCDictionarySource.cpp 等字典源使用,其单元测试位于 src/Dictionaries/tests/gtest_external_query_builder.cpp。
字典源数据竞争修复(PR #103277):ClickHouse、MySQL、PostgreSQL 和 XDBC 字典源中,clone() const读取与isModified() const写入同一invalidate_query_response字符串,构成数据竞争,本次修复。
其他字典相关修复:
DataLakeCatalog现在会尊重服务器的http_forbid_headers配置来校验auth_header设置(PR #98827);- postgres 数组解析的下溢修复(PR #104322)。
索引与数据一致性修复
| 修复项 | 说明 | 修复 PR |
|---|---|---|
| ALIAS 列上的 text/bloom filter 跳过索引被静默忽略 | 当表达式含 lambda 捕获常量时(如arrayMap((k, v) -> concat(k, '=', v), mapKeys(m), mapValues(m))) | #103708 |
| JSON 列数据 part 检查与一致性检查 | 此前可能对缺失文件产生误报 | #103858 |
| 动态结构类型的数据 part 一致性检查 | 并检测损坏的columns_substreams.txt(#103858 的增强版重提交) | #104888 |
备份/恢复与 Keeper 修复
| 修复项 | 说明 | 修复 PR |
|---|---|---|
复制表RESTORE的 Keeper 重试预算 | 恢复后的 part 挂载使用backup_restore_keeper_max_retries而非常规插入的 Keeper 重试预算 | #104610 |
| Keeper 终止/重启循环 | 当get /keeper/availability_zone携带quorum_reads=true发送给未配置<placement>的 Keeper 时 | #104663 |
协议兼容性与其他修复
- 客户端向后兼容(PR #103148):修复旧客户端通过
remote()或分布式表向新服务器插入时因processInsertQuery末尾无条件发送sendProgress导致的UNEXPECTED_PACKET_FROM_SERVER错误。这是重要的协议兼容修复,升级服务器后旧客户端插入不再报错。 - JIT 编译修复(PR #105048):修复
toUInt128(<Float64 表达式>)等 Float 转 UInt128 表达式 JIT 编译时的CANNOT_COMPILE_CODE Could not find symbol __fixunsdfti——unsigned 128 位 float-to-int 的 compiler-rt builtin 此前缺失于 JIT 符号解析器(issue #105031)。 - JSON 列 GROUP BY 修复(PR #100758):当向 JSON 列插入的行引入新动态字段(与已存在字段类型不兼容),且该列随后被用作 GROUP BY 键时可能出现的异常。
- IN (subquery) 移到 PREWHERE 的 "Not-ready Set" 异常(PR #100375):当优化器把带
IN (subquery)的过滤器移动到 PREWHERE 时抛出异常。
构建/测试改进
本版本包含 1 项构建/测试改进:为函数实现压力测试,检查函数各种性质的健全性(PR #93543)。这属于持续提升函数正确性的测试基础设施投入。
此外还包括若干"NOT FOR CHANGELOG / INSIGNIFICANT"级别的内部修复,如 Keeper 组件跟踪守卫补充、刷新物化视图SECONDARY_CREATE的 sanity checks 放宽、以及一个测试稳定性修复(03706_statistics_preserve_checksums_on_mutations)。
升级评估与排查建议
综合上述内容,升级到 v26.3.11.36-lts 时应重点关注:
安全检查优先:如使用了 PostgreSQL / Cassandra / XDBC 字典源且字典键可能包含单引号,请优先升级——这是可被利用的 SQL 注入漏洞(CVE 级风险)。修复原理见上文
ExternalQueryBuilder的''转义(src/Dictionaries/ExternalQueryBuilder.cpp)。FINAL 查询性能:如果你有事件日志类表(同一主键行不可能跨分区)且 26.3 升级后
FINAL查询明显变慢,可评估设置defer_partition_pruning_after_final = 0恢复快速路径。该设置在 src/Core/Settings.cpp 中定义,仅影响分区键列不在排序键中的分区表。查询结果变化:
optimize_inverse_dictionary_lookup的边界修复、JOIN 下推修复、RIGHT ANY JOIN 修复会改变受影响查询的结果——升级后建议对依赖这些特性的查询做结果回归验证。旧客户端兼容:
remote()/ 分布式表插入的UNEXPECTED_PACKET_FROM_SERVER问题已修复,升级服务器后可验证旧版本客户端的插入链路。JSON 相关修复:如果使用 JSON 列并曾遇到"缺失文件误报"或 GROUP BY 异常,本版本已修复。
如何查看与应用该版本
- 阅读完整 changelog:docs/changelogs/v26.3.11.36-lts.md;
- 查看版本历史与聚合变更:CHANGELOG.md;
- 设置项的完整定义与默认值:见 src/Core/Settings.cpp 中对应
DECLARE块; - 行为变更的版本历史追踪:见 src/Core/SettingsChangesHistory.cpp。
部署与验证方式:在服务器上运行clickhouse-server并执行SELECT version()确认版本;对设置类变更可通过SET defer_partition_pruning_after_final = 0;会话级验证,或写入config.xml的<profiles>节点持久化。
【免费下载链接】ClickHouseClickHouse® is a real-time analytics database management system项目地址: https://gitcode.com/GitHub_Trending/cli/ClickHouse
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考