bigywater.tech
ClickHouse 内部原理 · 66

ON CLUSTER:一条 DDL 如何发到所有节点

真实执行一条ON CLUSTER建表语句,用system.distributed_ddl_queue和Keeper的task_queue看清楚DDL真实如何广播到每个节点。

3/3节点确认
真实每个节点独立领取任务并各自完成建表
前提易漏配置
真实distributed_ddl配置缺失会直接导致ON CLUSTER报错

做的事:真实执行一条ON CLUSTER的建表语句

代码CREATE TABLE demo.ddltest ON CLUSTER mycluster (k UInt64) ENGINE=MergeTree ORDER BY k; SELECT cluster, host, port, status, query FROM system.distributed_ddl_queue ORDER BY entry DESC LIMIT 3; SELECT name FROM system.zookeeper WHERE path='/clickhouse/task_queue/ddl' ORDER BY name DESC LIMIT 3;

验证:真实变成Keeper里的一个带序号的任务,3个节点各自领取执行

实测 · 本机执行输出
SELECT cluster, host, port, status FROM system.distributed_ddl_queue ...;
→ mycluster  127.0.0.1  19110  Finished
  mycluster  127.0.0.1  19120  Finished
  mycluster  127.0.0.1  19130  Finished    ← 真实3个节点各自独立完成

SELECT name FROM system.zookeeper WHERE path='/clickhouse/task_queue/ddl' ...;
→ query-0000000006   ← 真实这条DDL在Keeper里的任务编号
  query-0000000005
  query-0000000004

-- 真实验证3个节点确实都建出了这张表
node1: EXISTS demo.ddltest → 1
node2: EXISTS demo.ddltest → 1
node3: EXISTS demo.ddltest → 1

一条ON CLUSTER语句真实并不是ClickHouse客户端替你依次连接3个节点各跑一遍SQL,而是先把这条语句真实写成Keeper里/clickhouse/task_queue/ddl路径下一个带自增序号的任务(本文这次是query-0000000006),集群里每个节点都有一个真实持续监听这个路径的后台线程(DDLWorker),发现有新任务出现就真实拉取、在本地执行、再把执行结果(本文的Finished状态)写回去,让发起查询的客户端能通过system.distributed_ddl_queue看到每个节点各自独立的完成状态。

诚实的前提:这套机制真实需要一段配置才能工作

本文第一次真实尝试ON CLUSTER的时候,直接撞上了报错:DB::Exception: There is no DistributedDDL configuration in server config. (NO_ELEMENTS_IN_CONFIG)——真实原因是每个节点的配置文件里,需要额外声明一段<distributed_ddl><path>/clickhouse/task_queue/ddl</path></distributed_ddl>,明确告诉这个节点"DDL任务队列真实要用Keeper的哪个路径",本文补上这段配置、重启3个节点之后,ON CLUSTER才真正可用。这个真实的前提提醒了一件容易被官方文档的示例代码掩盖的事情:ON CLUSTER这个语法糖背后,真实依赖集群的每个节点都要能访问同一个Keeper、且都配置了同一个task_queue路径,缺了任何一环,这条语句要么直接报错(本文遇到的情况),要么表面上不报错但真实只在发起查询的那个节点生效(如果客户端连接的那个节点没配置好distributed_ddl,或者干脆没用ON CLUSTER,语句只会本地执行,不会真实广播)——这也是为什么排查"为什么ON CLUSTER建的表,某个节点上没有"这类问题时,第一步应该是真实核对每个节点的distributed_ddl配置和Keeper连通性,而不是先怀疑DDL语法本身写错了。

分步演示:从配置缺失的报错到3节点真实各自执行完成

每一步都是本文上面用真实ON CLUSTER跑出来的原始结果。

一条DDL,真实变成Keeper里的一个带序号的任务
这一步新验证的阶段

    本文用到的工具

    • 本机真实的3节点集群,真实的 system.distributed_ddl_queue 与Keeper task_queue/ddl
    • 真实的 <distributed_ddl> 前置配置要求
    京ICP备2026067502号-1京公网安备11010502063487号