Supabase Pipelines 怎么把 Postgres 变更复制到 ClickHouse 并配置权限?
【免费下载链接】supabaseThe Postgres development platform. Supabase gives you a dedicated Postgres database to build your web, mobile, and AI applications.项目地址: https://gitcode.com/GitHub_Trending/supa/supabase
Supabase Pipelines 是托管的 CDC 产品,基于 Postgres 逻辑复制,把数据库变更从 Supabase Postgres 持续发送到目标系统。本文以 ClickHouse 为目标,说明如何准备 ClickHouse 端资源与权限、配置复制目标,并验证变更确实到达了 ClickHouse。适用前提:Supabase Pipelines 目前处于 public alpha,而 ClickHouse destination 处于 Early Access,仅对通过审核的组织开放,需要先申请 Early Access 权限再按本文操作;ClickHouse 必须能通过公网 HTTPS 访问(HTTP、localhost、私有或内网主机名均不被支持)。
准备 ClickHouse 资源与权限
在创建 destination 之前,在 ClickHouse 侧完成以下准备:
- 创建或选定一个用于承载复制表的 ClickHouse 数据库;
- 为 Pipelines 创建一个专用 ClickHouse 用户;
- 授予该用户目标数据库的访问权限。Pipelines 需要该用户能够:
- 查询
system.databases、system.tables、system.columns - 创建、修改、truncate 和删除表
- 使用
ReplacingMergeTree时创建和删除视图 - 向托管表插入数据
- 查询
- 复制该数据库的 HTTPS 端点,需要时带上端口。Pipelines 会拒绝 HTTP 端点和私有/内网主机名。
除上述对象外保持数据库空着:复制表和 current-state 视图由 Pipelines 托管,不要预先创建或手动修改这些对象,否则可能导致表初始化或写入失败。
版本要求:默认的ReplacingMergeTree引擎要求 ClickHouse23.5 或更新版本;MergeTree事件日志引擎没有最低版本要求。
准备 Postgres publication
Pipelines 复制哪些表和变更类型由 Postgres publication 定义。可以先用 SQL 创建,之后在 Dashboard 中选择它。文档给出的示例假设数据库中有users和orders两张表:
-- 为指定表创建 publication create publication pub_users_orders for table users, orders;该 publication 会跟踪这两张表的所有变更(INSERT、UPDATE、DELETE、TRUNCATE)。其他可选写法包括按 schema 发布(for tables in schema public)、发布全部表(for all tables)、只发布部分列或按行过滤。FOR ALL TABLES会包含 Supabase 托管的 schema(包括 Pipelines 内部创建的etl表),除非你确实要复制库中所有符合条件的表,否则建议用FOR TABLES IN SCHEMA public或显式列出应用表。
对 ClickHouse 目标,源表必须满足以下要求(来自源表要求表):
| 场景 | 是否支持 | 要求 |
|---|---|---|
ReplacingMergeTree表没有主键 | 否 | 添加源主键、把主键列全部加入 publication,或改用MergeTree事件日志布局 |
仅插入的MergeTree表没有主键 | 是 | 插入不需要行标识 |
| 有主键的表 | 是 | publication 必须包含每一个主键列 |
| 使用主键 replica identity 的更新 | 否 | 改用REPLICA IDENTITY FULL,使未改动的列值也能重建 |
| 使用主键 replica identity 的删除 | 是 | publication 必须包含所有主键列 |
使用REPLICA IDENTITY FULL的更新或删除 | 是 | full identity 提供更新所需的完整行镜像 |
使用REPLICA IDENTITY USING INDEX的更新 | 否 | 改用REPLICA IDENTITY FULL |
使用REPLICA IDENTITY USING INDEX的删除 | 有限 | 仅当选定索引与源主键解析到相同列;其他唯一索引不支持 |
使用REPLICA IDENTITY NOTHING的更新或删除 | 否 | 删除需要主键或 full identity,更新需要 full identity |
另外,顶层 Postgres 数组列的元素可以可空,但列本身不能为NULL——ClickHouse 的 RowBinary 格式无法编码顶层NULL数组。需要先把已有NULL值替换掉并将源列改为NOT NULL,或保证生产者总是写入数组值;空数组支持。
在 Dashboard 配置 ClickHouse destination
Managed Pipelines 运行在AWSeu-central-1(法兰克福),无法更改。条件允许时,把 ClickHouse 服务部署在靠近法兰克福的位置,以减少网络延迟和复制延迟。
配置步骤:
- 打开 Dashboard 的Database > Replication;
- 点击Add destination;
- 选择ClickHouse。如果列表中没有,说明组织尚未获得 Early Access,需要先申请;
- 选择一个 Postgres publication,输入 destination 名称;
- 填写 ClickHouse 设置:
- URL:HTTPS 端点,需要时带端口
- User:前面创建的专用 ClickHouse 用户
- Password:如认证需要则填写该用户密码
- Database:已存在的目标数据库
- Table engine:选ReplacingMergeTree得到当前状态表,或选MergeTree得到 append-only 事件日志
- 点击Create and start pipeline。
两种引擎的区别:
| 引擎 | 数据模型 | 源主键 | 查询方式 |
|---|---|---|---|
ReplacingMergeTree(默认) | 当前状态表 | 必需 | 查询生成的<table>__current视图 |
MergeTree | Append-only CDC 事件历史 | 仅插入表可选 | 查询基表 |
ReplacingMergeTree下,Pipelines 会用源主键作为 ClickHouse 的排序与去重键,添加_etl_version UInt128排序列和_etl_deleted UInt8墓碑列,并创建<table>__current视图(对基表运行FINAL并过滤已删除行)。MergeTree下则添加cdc_operation(INSERT/UPDATE/DELETE)和cdc_lsn(Postgres 提交 LSN)两个列。_etl_version、_etl_deleted、cdc_operation、cdc_lsn都是保留名,源列不能使用这些名字。
表名映射规则:每个 Postgres schema.table 对应一张 ClickHouse 表,已有的下划线会被翻倍,schema 与表名之间用一个下划线连接。文档示例:
| Postgres 表 | ClickHouse 表 |
|---|---|
public.orders | public_orders |
my_schema.logs | my__schema_logs |
复制到 ClickHouse 时,Postgres schema 和表名不能以_开头或结尾,也不能包含"或;。
验证复制结果
在Database > Replication页面,目标会以列表形式出现,先确认 pipeline 状态:
- pipeline 状态为Running表示正在复制;Failed时把鼠标悬停在状态上可看错误摘要,点击View pipeline查看详细信息;
- 点击View pipeline进入状态页,确认各表状态进入Live(表示该表正在接收持续复制;初始同步阶段会经历Queued→Copying→Copied→Live);
- 状态页的Waiting to sync表示尚未确认 flush 的 WAL 字节数,Caught up表示该 slot 当前所有变更都已确认;Slot status为Reserved/Extended属健康状态,Unreserved和Lost需要处理。
数据层面,对ReplacingMergeTree目标,查询生成的 current-state 视图。文档给出的示例(表名按前面的映射规则得到):
select * from "public_orders__current";注意在 ClickHouse 后台 merge 完成前,直接不带FINAL查询基表可能返回同一源行的多个版本,常规当前状态查询应使用__current视图。Pipelines 不会执行OPTIMIZE ... FINAL CLEANUP,物理墓碑的清理由 ClickHouse 运维方按自己的存储保留策略负责。对MergeTree目标,直接读取基表分析事件历史;同一个 Postgres 事务中的多条变更会共享同一个cdc_lsn,它不是唯一事件 ID,也不是重建当前状态的总序。
常见失败与对应处理
ClickHouse 目标文档给出的排查表:
| 问题 | 处理 |
|---|---|
| destination 列表中没有 ClickHouse | Early Access 期间该 destination 按组织灰度,先申请访问权限 |
| URL 校验失败 | 使用公网 ClickHouse HTTPS 端点并带端口;HTTP、localhost、私有/内网端点不支持 |
| 连接失败 | 确认端点可从互联网访问,用户名和密码正确 |
| 数据库校验失败 | 创建配置中指定的数据库,并授予用户读取system.databases的权限 |
| 校验通过但建表或写入失败 | 按上文清单授予目标数据库权限;检查是否存在与生成名冲突的表或视图;不要手动修改托管对象 |
ReplacingMergeTree初始化失败 | 确认服务器为 ClickHouse 23.5 或更新,且每张源表都有已发布的主键 |
| 更新或删除失败 | 更新使用REPLICA IDENTITY FULL;删除可用主键 identity 或 full identity;所有 identity 列都要包含在 publication 中 |
| 可空数组复制失败 | 替换顶层NULL数组值并将源列改为NOT NULL,或保证生产者总是写入数组;空数组支持 |
| schema 变更失败 | 对照下方支持范围;ClickHouse DDL 非事务性,可能部分应用,不要手动修复托管对象,带 pipeline ID 和错误详情联系支持 |
Schema 变更方面,Early Access 期间支持:加列、改名(嵌套子列移到不同父级除外)、删列、去掉已有标量列的NOT NULL、增改删支持的列默认值。不会自动应用:改列类型、给已有可空列加NOT NULL、ReplacingMergeTree下变更/删除/重命名源主键列、重命名源表或 schema。中断的多列变更可能留下部分应用的目标 schema,文档明确不要手动修复托管表或视图;pipeline 重启后仍失败则联系支持。
限制与运行中注意事项
- Early Access 期间使用
ReplacingMergeTree时,源主键值必须不可变。更新主键值会导致旧键在生成的 current-state 视图中仍然可见,该限制会在主键更新能力可用时移除。 - 源端
TRUNCATE会 truncate 对应 ClickHouse 表(两种引擎都如此);重置某张表会删除并重建该表(ReplacingMergeTree还包括其生成视图),该表之前累积的目的地数据在新初始同步开始前会清空。 - Pipelines 是 at-least-once 处理:罕见恢复场景下已确认的批次可能被重复处理。默认的
ReplacingMergeTree布局维护当前状态表可吸收重复;MergeTree保存 append-only 历史,消费端必须容忍重复事件。 - 源表加入或移出 publication 后,需要重启 pipeline 才生效。
下一步
- 复制延迟、slot 状态(Unreserved/Lost)与日志排查,见 Monitor pipeline status。
- publication 的高级选项(列选择、行过滤、分区表
publish_via_partition_root)与 pipeline 高级设置(Batch wait time、Table sync workers、Copy connections per table、Invalidated slot behavior),见 Set up Pipelines。 - 更多问题与限制说明,见 Pipelines FAQ 与 ClickHouse destination。
【免费下载链接】supabaseThe Postgres development platform. Supabase gives you a dedicated Postgres database to build your web, mobile, and AI applications.项目地址: https://gitcode.com/GitHub_Trending/supa/supabase
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考