ClickHouse分布式DDL(ON CLUSTER)执行与副本同步
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 CLUSTER的distributed_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)