ClickHouse v21.6.3.14-stable 补丁版解析:S3 零拷贝复制、LDAP 角色映射与复制队列稳定性修复
【免费下载链接】ClickHouseClickHouse® is a real-time analytics database management system项目地址: https://gitcode.com/GitHub_Trending/cli/ClickHouse
导读
本篇文章基于当前仓库 docs/changelogs/archive/v21.6.3.14-stable.md 的发布说明,系统梳理 ClickHouse v21.6 系列第二个稳定补丁版(v21.6.3.14-stable)相对 v21.6.2.7-prestable 引入的全部 2 项改进与 5 项 Bug 修复。文中将逐条还原每个修复对应的技术背景、问题根因与影响范围,并结合当前仓库源码(如src/Disks/DiskObjectStorage、src/Access/LDAPAccessStorage.cpp、src/Storages/MergeTree等)给出源码级佐证,帮助读者判断该补丁与自己生产环境的关联程度,并据此制定升级与验证策略。
一、版本背景:stable 补丁版在发布节奏中的定位
ClickHouse 的发布流程分为 prestable 与 stable 两条线:功能特性先在-prestable版本中合入,经过回归验证后进入-stable分支,而形如v21.6.3.14-stable的补丁版本则是在主版本发布后,针对回归缺陷与高优先级问题的小步快修版本。本补丁直接对比对象是v21.6.2.7-prestable,说明它是 v21.6 主版本线在向稳定态收敛过程中的一次集中修复。
本补丁值得关注的原因在于:修复面覆盖了存储层(S3 零拷贝复制、低内存下 merge 失败)、访问控制层(LDAP 角色映射死锁)、复制与数据一致性层(ZooKeeper 断连后的复制队列脏数据)、HTTP 协议层(multipart/form-data 边界解析)以及列式格式层(Arrow 堆缓冲区溢出),属于典型的"发布后集中收口"版本。
二、Improvement:两项行为改进
2.1 修复多 S3 volume 场景下的 Zero-Copy 复制
原文条目:Fix Zero-Copy replication with several S3 volumes(Fixes #22679),对应 PR #22864。
问题背景:零拷贝复制(Zero-Copy Replication)是 ClickHouse 针对对象存储(S3、Azure Blob Storage 等)设计的一种复制优化。与本地磁盘复制不同,它不把数据 part 实际拷贝到每个副本,而是让所有副本共享同一个底层对象存储对象,仅通过 ZooKeeper 复制元数据与 part 的"引用关系",从而大幅节省存储空间与网络开销。
问题根因:当一张复制表被配置在多个 S3 volume上时,不同 part 可能落在不同的 bucket / 存储桶组合中,零拷贝复制的元数据路由逻辑若不能正确处理这种多 volume 分布,会导致副本间元数据不一致或 part 归属错乱。
源码佐证:当前仓库 src/Disks/DiskObjectStorage/DiskObjectStorage.h 中定义了supportZeroCopyReplication():
/// Keeper metadata replicates itself; in-memory metadata is transient and has no local /// metadata files zero-copy could ship (see `getReplicatedFilesDescriptionForRemoteDisk`). bool supportZeroCopyReplication() const override { return metadata_storage->getType() != MetadataStorageType::Keeper && metadata_storage->getType() != MetadataStorageType::Memory; }这说明零拷贝复制的能力与元数据存储类型强绑定(Keeper / 内存元数据不支持),只有普通对象存储元数据才可启用;同一磁盘还需具备"将本地路径映射到对象存储对象"的元数据机制(见 src/Disks/DiskObjectStorage/DiskObjectStorage.h 中关于 metadata 的描述)。零拷贝复制是可选配置项,生产环境若使用对象存储,需在表引擎或磁盘配置中显式开启,并验证多 volume 场景下的复制行为。
2.2 标量子查询不再吞掉超限错误
原文条目:Avoid hiding errors like
Limit for rows or bytes to read exceededfor scalar subqueries。
问题背景:标量子查询(scalar subquery)要求查询最多返回一行。此前某些内部处理路径会把子查询执行过程中的限制类异常(如Limit for rows or bytes to read exceeded,即max_rows_to_read/max_bytes_to_read等配额被触达)吞掉或改写,导致用户无法看到真正的原因。
修复效果:本补丁后,标量子查询在触达行数/字节数读取上限时,错误信息能够如实透传给客户端,便于定位是数据量问题还是配额配置问题。
三、Bug Fix:五类稳定性与正确性修复
3.1 multipart/form-data 消息中 boundary 前 CRLF 的处理
原文条目:In "multipart/form-data" message consider the CRLF preceding a boundary as part of it(Fixes #23905)。
问题背景:HTTP 接口以multipart/form-data上传数据时,boundary(分界符)之前的 CRLF(回车换行)在协议语义中属于该消息的一部分。如果解析器忽略这一点,可能把分界符前的空行误判为数据内容,导致多部分消息的切分错位。
修复效果:解析逻辑把 boundary 前的 CRLF 纳入边界判定,保证各 part 的内容切分严格符合协议。当前仓库中 S3 / 对象存储相关的 HTTP 客户端均包含 multipart 组装与解析逻辑(见 src/IO/S3/Client.cpp、src/IO/S3/PocoHTTPClient.cpp),说明该类边界处理对上传路径的正确性至关重要。
3.2 LDAP 角色(重)映射期间的死锁
原文条目:Fixed the deadlock that can happen during LDAP role (re)mapping, when LDAP group is mapped to a nonexistent local role。
问题背景:ClickHouse 的 LDAP 认证支持把 LDAP 组动态映射到本地角色(role),从而实现对用户权限的集中管理。此前当映射目标是不存在的本地角色时,角色重映射过程可能因加锁顺序问题触发死锁,导致访问控制模块卡死。
修复效果:在 LDAP 角色映射/重映射路径上修复了锁竞争,使"映射到不存在的角色"这类配置错误不再导致服务不可用。
源码佐证:LDAP 访问存储实现在 src/Access/LDAPAccessStorage.cpp,其中setConfiguration在持锁状态下更新 LDAP 服务器配置,角色解析、映射与访问控制通知通过 src/Access/ExternalAuthenticators.cpp 联动,锁的嵌套获取是死锁风险的典型来源。若你在配置中使用了 LDAP 组到角色的映射,建议升级后重点回归验证动态加角色/删角色的场景。
3.3 ZooKeeper 断连后的复制队列脏数据与相交虚拟 parts 崩溃
原文条目(两条):
- If ZooKeeper connection was lost and replica was cloned after restoring the connection, its replication queue might contain outdated entries. It's fixed.
- Fixed crash when replication queue contains intersecting virtual parts. Print error in log instead of terminating.
问题背景:ReplicatedMergeTree 的所有变更(插入、merge、mutation)都先写入 ZooKeeper 的复制日志(log),各副本通过复制队列(replication queue)异步拉取执行。存在两类隐患:
- 断连后克隆副本:副本与 ZooKeeper 连接丢失期间,若重新连接后该副本执行了"克隆"(从其他副本复制 part),其本地复制队列中可能残留连接中断前的过期条目,导致重复执行或与已克隆数据冲突。
- 相交的虚拟 parts:复制队列中若出现相互重叠的虚拟 parts(通常发生在某数据 part 意外丢失后),旧逻辑直接终止进程(crash),可用性差。
修复效果:断连场景下清理/校正过期队列条目;对相交虚拟 parts 改为记录错误日志而非终止进程,提升容错性。复制队列实现位于 src/Storages/MergeTree/ReplicatedMergeTreeQueue.h,日志条目结构见 src/Storages/MergeTree/ReplicatedMergeTreeLogEntry.h。若你的集群经历过 ZooKeeper 抖动或 part 丢失,这条修复直接关系到能否在不重启副本的情况下自愈。
3.4Mutation was killed异常被过早抛出
原文条目:Fix bug when exception
Mutation was killedcan be thrown to the client on mutation wait when mutation not loaded into memory yet。
问题背景:执行ALTER TABLE ... DELETE/UPDATE(即 mutation)时,客户端通常需要等待 mutation 完成。此前在 mutation 尚未从 ZooKeeper 加载进副本内存、正等待加载的阶段,如果用户取消了等待,可能把Mutation was killed异常误抛给客户端,产生误导性报错。
修复效果:修正了 mutation 等待路径的状态判断,避免在"尚未加载"与"已被 kill"之间误报。mutation 的 ZooKeeper 条目定义见 src/Storages/MergeTree/ReplicatedMergeTreeMutationEntry.h。
3.5 低内存服务器上 merge 无法执行(需要重启)的罕见问题
原文条目:Fix extremely rare bug on low-memory servers which can lead to the inability to perform merges without restart(Possibly fixes #24603)。
问题背景:在内存较小的服务器上,merge 任务的调度/执行路径中存在一个罕见缺陷:一旦触发,所有后续 merge 都无法执行,只能通过重启恢复,严重影响后台合并吞吐与查询性能(未合并 part 增多)。
修复效果:修复后低内存环境下 merge 不再因该缺陷卡死,无需重启即可恢复后台合并能力。
3.6 Arrow 格式解析的堆缓冲区溢出风险
原文条目:Fix possible heap-buffer-overflow in Arrow。
问题背景:Arrow 是 ClickHouse 支持的表格式之一(可通过INSERT ... FORMAT Arrow/SELECT ... FORMAT Arrow与 Arrow 生态互操作使用)。解析外部传入的 Arrow 数据时存在潜在的堆缓冲区越界读写,属于安全与稳定性双相关的缺陷。
修复效果:对 Arrow 反序列化路径补充边界校验,杜绝越界访问。若你的链路中有外部系统以 Arrow 格式写入 ClickHouse,建议优先升级并配合回归验证。
四、升级与验证建议
- 优先升级场景:
- 使用 S3 / Azure 等对象存储并开启 Zero-Copy 复制,且配置了多个 volume 的集群;
- 使用 LDAP 认证且配置了角色映射的实例;
- 经历过 ZooKeeper 断连、part 丢失,或复制队列出现异常的副本;
- 对外开放 HTTP 上传接口(multipart/form-data)或以 Arrow 格式接入外部数据的服务。
- 回归测试重点:
- 多 S3 volume 下执行
SYSTEM SYNC REPLICA并检查各副本 part 元数据一致性; - 配置"映射到不存在角色"的 LDAP 组,验证认证与角色列表展示不卡死;
- 断连 ZooKeeper 后重新连接,观察复制队列是否有过期条目;
- 构造超行数限制的标量子查询,确认错误信息如实透出。
- 多 S3 volume 下执行
五、小结
v21.6.3.14-stable 是一个典型的"稳定化收口"补丁:没有新功能,但每一项修复都直指对象存储复制、LDAP 访问控制、复制队列一致性、mutation 状态机与外部格式解析等生产环境的高频痛点。建议相关场景的用户在充分回归后尽快升级,以获得更稳的复制行为与更少的异常崩溃。
【免费下载链接】ClickHouseClickHouse® is a real-time analytics database management system项目地址: https://gitcode.com/GitHub_Trending/cli/ClickHouse
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考