CodeWalk

ClickHouse分布式DDL(ON CLUSTER)执行与副本同步

作者:苦行僧 · 2026-05-30 12:55

ClickHouse中ON CLUSTER语句是如何在集群所有节点上执行DDL操作的?请解释分布式DDL的内部机制:DDL任务如何通过ZooKeeper分发、各节点如何执行、执行失败如何处理、以及如何查看DDL执行状态(system.ddl_queue/system.ddl_log)。给出一个添加列、删除分区和修改TTL的分布式DDL示例。

回答

苦行僧

ClickHouse分布式DDL(ON CLUSTER)详解:

1. 执行流程

用户 → clickhouse-client: ALTER TABLE t ON CLUSTER cluster ADD COLUMN x Int32
  ↓
1. 接收节点创建DDL任务 → 写入ZK: /clickhouse/task_queue/ddl/query-
  ↓
2. ZK通知集群所有节点
  ↓
3. 每个节点从ZK拉取DDL任务,解析后执行
  ↓
4. 执行结果写入ZK: /clickhouse/task_queue/ddl/query-/finished
  ↓
5. 发起节点收集所有节点的结果,返回给客户端

2. 支持的操作

-- 修改表结构(所有节点生效)
ALTER TABLE orders ON CLUSTER cluster ADD COLUMN discount Float32 DEFAULT 0;
ALTER TABLE orders ON CLUSTER cluster DROP COLUMN old_col;
ALTER TABLE orders ON CLUSTER cluster MODIFY COLUMN price Float64;
ALTER TABLE orders ON CLUSTER cluster COMMENT COLUMN price '含税单价';

-- 分区操作
ALTER TABLE orders ON CLUSTER cluster DROP PARTITION '202505';
ALTER TABLE orders ON CLUSTER cluster ATTACH PARTITION '202504';
ALTER TABLE orders ON CLUSTER cluster MOVE PARTITION '202503' TO TABLE orders_archive;

-- TTL操作
ALTER TABLE orders ON CLUSTER cluster MODIFY TTL event_time + INTERVAL 30 DAY;

3. 查看执行状态

-- 当前DDL队列
SELECT * FROM system.ddl_queue ORDER BY create_time DESC;
-- DDL历史
SELECT * FROM system.ddl_log ORDER BY event_time DESC;
-- 查看执行进度(通过ZK)
system zk ls /clickhouse/task_queue/ddl/

4. 执行失败的场景

  • 某节点宕机:DDL任务ZK保留,节点恢复后自动执行
  • 某节点超时:distributed_ddl_task_timeout(默认180秒)
  • 部分失败:可通过ON CLUSTERdistributed_ddl_output_mode查看

5. 最佳实践

# 配置分布式DDL超时
<distributed_ddl_task_timeout>600</distributed_ddl_task_timeout>
<distributed_ddl_output_mode>distributed</distributed_ddl_output_mode>
  • 大表ALTER推荐在低峰期执行
  • 先在一台节点执行dry run:不挂ON CLUSTER观察影响
  • 使用Replicated表时DDL会自动同步到副本(无需ON CLUSTER)