ClickHouse v22.8.13.20-lts 更新解析:三个用户可见 Bug Fix 的来龙去脉与源码印证
【免费下载链接】ClickHouseClickHouse® is a real-time analytics database management system项目地址: https://gitcode.com/GitHub_Trending/cli/ClickHouse
本篇以 ClickHouse 官方 Changelog 归档中的 v22.8.13.20-lts.md 为主体,完整覆盖该 LTS 补丁版本相对上一版 v22.8.12.45-lts 的全部变更内容:3 个用户可见 Bug Fix(位置参数越界异常、LowCardinality 字典远程读取失败、system.dictionaries 异常)以及 6 项内部流程改进。读完后,你将理解每条 changelog 记录的准确语义,并能结合仓库源码定位到对应错误抛出点,掌握排查上述三类问题时的验证思路。
一、这份 Changelog 记录了什么
ClickHouse 的每个正式版本都会在docs/changelogs/下生成一份 Markdown 归档,其中 2023 年及更早的旧版本被整理到 archive 目录。本文对应的 v22.8.13.20-lts.md 标题行为:
ClickHouse release v22.8.13.20-lts (e4817946d18) FIXME as compared to v22.8.12.45-lts (86b0ecd5d51)
这里有三处关键信息:
- 版本后缀
-lts表明这是 22.8 长期支持分支的补丁版本,而非主线(prestable/stable)开发版本;22.8.13.20中第 3、4 位分别是分支号与补丁号。 - 括号中的短哈希
e4817946d18是本次发布对应的 Git commit,可据此在仓库历史中精确定位该版本快照;上一版基线v22.8.12.45-lts对应86b0ecd5d51。 - "FIXME as compared to"表示本版本是相对于上一个 LTS 补丁的增量变更清单——它只列出两个基线之间合入的提交,而不是 22.8 分支自诞生以来的全部历史。因此阅读旧版 Changelog 时,必须把它视为“相邻版本差异”,而非完整特性列表。
该文件内容分为两个章节:
Bug Fix (user-visible misbehavior in official stable release):用户可见的行为修正,共 3 条,是运维升级决策的主要依据;NOT FOR CHANGELOG / INSIGNIFICANT:不面向用户的内部流程变更(发布脚本、CI/CD),共 6 条。
以下逐条展开。
二、Bug Fix 逐条解析
2.1 修复Positional argument out of bounds位置参数越界异常
Changelog 原文:
Backported in #45565: Fix positional arguments exception Positional argument out of bounds. Closes #40634. #41189 (Kseniia Sumarokova).
背景概念:ClickHouse 支持位置参数(positional arguments)语法——在查询的表达式位置直接写一个整数字面量,它会被解析为对SELECT列表中第 N 个列表达式的引用。例如SELECT 1, 2 WHERE 1 = 2中的1和2就是位置参数。该机制的替换逻辑在 src/Interpreters/replaceForPositionalArguments.cpp 中实现,replaceForPositionalArguments函数会遍历select()->children得到列表达式列表,并对候选字面量做类型与取值校验。
修复点:原实现对负数位置参数与越界值的边界判断存在缺陷,会错误地抛出Positional argument out of bounds异常。从源码结构看,该异常正是抛出点 replaceForPositionalArguments.cpp 第 61-62 行:
if (!pos || pos > columns.size()) throw Exception(ErrorCodes::BAD_ARGUMENTS, "Positional argument out of bounds: {} (expected in range [1, {}]", pos, columns.size());同文件中还保留了负数索引的越界分支(Negative positional argument number ... is out of bounds. Expected in range [-N, -1],见 第 47-53 行)。本次 backport(合入号 #45565,修复 #40634,PR #41189)修正的就是这条校验链路中的误报路径——即合法的参数组合被错误判定为越界。对使用位置参数写法的查询(尤其是通过 ORM 或程序化拼接生成的 SQL),升级该版本可消除一类误报异常。
2.2 二次修复Cannot read all data:LowCardinality 字典从远程文件系统读取失败
Changelog 原文:
Backported in #44997: Another fix for
Cannot read all dataerror which could happen while readingLowCardinalitydictionary from remote fs. Fixes #44709. #44875 (Nikolai Kochetov).
注意原文用词“Another fix”——说明此前已经有一轮针对同类错误的修复,本次是补漏。这提示阅读 Changelog 时应关注“Another/Second fix”这类措辞,它们往往意味着底层问题具有多个触发条件。
背景:LowCardinality字典是 ClickHouse 字典引擎的一种实现,其列数据采用低基数压缩编码存储;当字典源数据(如本地/远程文件)位于 S3 等远程文件系统时,读取会经过本地磁盘缓存层。Cannot read all data是底层读缓冲在“期望字节数与实际读取字节数不一致”时的通用错误,其典型抛出点包括:
- 通用读缓冲 src/IO/ReadBuffer.cpp 第 67 行:
"Cannot read all data. Bytes read: {}. Bytes expected: {}."; - 磁盘缓存读缓冲 src/Disks/IO/CachedOnDiskReadBufferFromFile.cpp 第 2013 行:
"Cannot read all data. Offset: {} (initial offset: {}), read bytes {}/{}"; - S3 读缓冲 src/IO/ReadBufferFromS3.cpp 第 249 行 还会附带 Key、size、expected size 与位置信息,便于定位具体对象。
从源码结构看,CachedOnDiskReadBufferFromFile正是远程文件经本地缓存读取时的关键组件,与本次“LowCardinality 字典 + remote fs”的报错场景吻合:反序列化 LowCardinality 字典数据时,某次读取在缓存/S3 路径上提前结束,导致字节数不匹配。本次 backport(#44997,修复 #44709,PR #44875)补上了剩余触发路径。
排查建议:若在低版本上遇到该错误,可先确认字典的source配置(是否指向远程对象存储)、本地cache目录是否可写以及缓存文件是否损坏,再评估升级到包含此修复的 LTS 补丁。
2.3 修复SELECT ... FROM system.dictionaries因坏结构字典而抛异常
Changelog 原文:
Backported in #45550: Fix
SELECT ... FROM system.dictionariesexception when there is a dictionary with a bad structure (e.g. incorrect type in xml config). #45399 (Aleksei Filatov).
背景:system.dictionaries是 ClickHouse 的字典系统表,用于枚举实例中已加载的字典及其元数据。原问题在于:只要实例中存在任何一个结构不合法的字典——例如字典 XML 配置里声明了错误的列类型——那么对system.dictionaries的任意查询都会整体抛异常,而不是优雅地跳过或返回该字典的错误信息。这对生产环境的可观测性是严重伤害:一个坏字典会“拖垮”所有基于系统表的监控查询。
本次修复(backport 编号 #45550,PR #45399)使查询system.dictionaries时不再因个别字典结构非法而中断。对于通过 XML 配置文件管理字典的部署(配置示例可参考仓库文档中的字典配置章节),这提升了系统表的健壮性:坏字典仍应被单独修正,但它不会再阻塞全局的字典巡检。
三、NOT FOR CHANGELOG:内部流程变更(6 条)
这些条目不改变用户可见行为,但对理解 ClickHouse 的发布机制有参考价值。全部 6 条原文如下:
- 自动合并绿色 backport PR 与绿色 approved PR(PR #41110,Mikhail f. Shiryaev):CI 通过后的回溯合并实现自动化,降低 LTS 分支人工同步成本——这正是本文这份 22.8 归档 Changelog 得以按时产出的流程基础。
- 改进发布脚本(PR #45074):加固 release 构建与发布工具链。
- 修正
approved_at取值并简化条件(PR #45302):修复自动合并流程中时间戳判断错误。 - 弃用 Artifactory,改用 R2 + ch-repos-manager(PR #45421):发布产物托管迁移到对象存储,降低基础设施耦合。
- 在 release workflow 中从
GITHUB_TAG去掉refs/tags/前缀(PR #45636):修正发布工作流中标签变量的格式问题。 - 合入普通系统表修复分支(PR #38262 / #45650,alesapin):从功能分支回溯的普通系统表修正。
从条目构成可以推断,22.8 LTS 分支在该阶段的主要维护重心已从功能开发转向发布流程自动化与基础设施迁移,符合 LTS 分支“只接受 backport 修复”的维护策略。
四、如何阅读与核验此类 LTS Changelog
结合 v22.8.13.20-lts.md 的结构,阅读同类归档文件时建议遵循以下方法:
- 先看标题行的两个 commit 哈希:确认增量对比基线,避免把“相对上一补丁的差异”误读为“相对 GA 版本的全部变化”。
- 区分两类章节:
Bug Fix (user-visible ...)是升级决策依据,应逐条对照自身业务场景(是否用了位置参数、字典是否走远程存储、是否依赖system.dictionaries);NOT FOR CHANGELOG章节可快速扫过,仅当排查发布产物或 CI 问题时再关注。 - 善用 “Backported in #N” 编号:它指向目标版本分支上的回溯合入记录,可据此在版本历史中还原修复的完整链条(主线 PR → backport PR → 版本发布)。
- 在源码中定位错误字符串:Changelog 中用反引号标出的错误信息(如
Positional argument out of bounds、Cannot read all data)通常就是源码中throw Exception(...)的字面量,可直接在src/下全文检索定位抛出点,如本文引用的 replaceForPositionalArguments.cpp#L62 与 ReadBuffer.cpp#L67,从而把 changelog 描述与实际执行路径对应起来。 - 注意同一条 Changelog 文件可能被多次归档:
docs/changelogs/目录中按版本存在 600 余份归档文件,排查历史版本问题时可按文件名(v<大版本>.<小版本>.<分支>.<补丁>-lts.md的命名规律)直接检索。
五、小结
v22.8.13.20-lts 是一个典型的小补丁 LTS 版本:3 个用户可见修复分别覆盖SQL 解析层(位置参数越界误报)、存储/IO 层(LowCardinality 字典远程读取的二次修复)、元数据层(system.dictionaries 健壮性),外加 6 条发布流程改进。对仍运行 22.8 分支的生产集群而言,若业务涉及位置参数写法、远程存储字典或系统表监控,升级到包含此补丁的版本可消除上述三类已知故障路径;验证方式即为升级后重新执行此前报错的查询并核对system.dictionaries可正常查询。
【免费下载链接】ClickHouseClickHouse® is a real-time analytics database management system项目地址: https://gitcode.com/GitHub_Trending/cli/ClickHouse
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考