建议 ClickHouse Cloud 用户使用 ClickPipes 将 PostgreSQL 复制到 ClickHouse。该方案原生支持 PostgreSQL 的高性能 CDC (变更数据捕获) 。
MaterializedPostgreSQL 引擎的数据库会为 PostgreSQL 数据库创建快照,并加载所需的表。所需表可以是指定数据库中任意 schema 子集下的任意表子集。创建快照的同时,数据库引擎还会获取 LSN;在完成表的初始转储后,便开始从 WAL 拉取更新。数据库创建完成后,之后新增到 PostgreSQL 数据库中的表不会自动加入复制,必须使用 ATTACH TABLE db.table 查询手动添加。
复制基于 PostgreSQL Logical Replication Protocol 实现。该协议不支持复制 DDL,但能够识别是否发生了会破坏复制的变更 (如列类型变更、添加/删除列) 。检测到此类变更后,对应表将停止接收更新。此时,应使用 ATTACH/ DETACH PERMANENTLY 查询重新完整加载该表。如果 DDL 不会破坏复制 (例如重命名列) ,表仍会继续接收更新 (insert 按位置执行) 。
该数据库引擎属于 Experimental。要使用它,请在配置文件中将
allow_experimental_database_materialized_postgresql 设为 1,或使用 SET 命令:创建数据库
host:port— PostgreSQL 服务器的端点。database— PostgreSQL 数据库名。user— PostgreSQL 用户。password— 用户密码。
使用示例
动态将新表添加到复制范围中
MaterializedPostgreSQL 数据库后,它不会自动检测对应 PostgreSQL 数据库中的新表。此类表可以手动添加:
动态将表从复制中移除
PostgreSQL schema
- 一个
MaterializedPostgreSQL数据库引擎对应一个 schema。需要使用设置materialized_postgresql_schema。 表 只通过表名访问:
- 对于一个
MaterializedPostgreSQL数据库引擎,可以指定任意数量的 schema 及其对应的一组表。需要使用设置materialized_postgresql_tables_list。每个表都必须连同其所属 schema 一起写出。 访问表时需要同时使用 schema 名称和表名:
materialized_postgresql_tables_list 中的所有表都必须写明其 schema 名称。
需要设置 materialized_postgresql_tables_list_with_schema = 1。
警告:在这种情况下,表名中不允许包含点号。
- 对于单个
MaterializedPostgreSQL数据库引擎,可以指定任意数量的 schema 及其完整的表集。需要使用设置materialized_postgresql_schema_list。
要求
-
在 PostgreSQL 配置文件中,wal_level 设置的值必须为
logical,并且max_replication_slots参数的值必须至少为2。 - 每个被复制的表都必须具有以下 副本标识 之一:
- 主键 (默认)
- 索引
不支持 TOAST 值的复制。将使用该数据类型的默认值。
设置
materialized_postgresql_tables_list
materialized_postgresql_schema
materialized_postgresql_schema_list
materialized_postgresql_max_block_size
- 正整数。
65536。
materialized_postgresql_replication_slot
materialized_postgresql_snapshot 搭配使用。
materialized_postgresql_snapshot
materialized_postgresql_replication_slot 一起使用。
materialized_postgresql_tables_list 无法更改。要更新该设置中的表列表,请使用 ATTACH TABLE 查询。
materialized_postgresql_use_unique_replication_consumer_identifier
0。
如果设置为 1,则允许将多个 MaterializedPostgreSQL 表配置为指向同一个 PostgreSQL 表。
materialized_postgresql_use_extended_date_and_time_types
date 和 timestamp/timestamptz 类型映射到 ClickHouse 的 Date32 和 DateTime64,以覆盖 PostgreSQL 这些类型更宽的取值范围。默认值:1。
如果将其设为 0,则改用范围更窄的 Date 和 DateTime 类型 (超出其范围的值,或带有子秒级精度的值,将无法表示) 。
此设置仅控制创建嵌套表时,类型推断所选择的列类型,因此必须在 CREATE DATABASE 时指定。之后无法通过 ALTER DATABASE ... MODIFY SETTING 修改它 (已创建的嵌套表会保留其固定的列类型,因此此类更改会被拒绝) ;如需更改,只能重新创建数据库。它不适用于 MaterializedPostgreSQL 表引擎,因为该引擎中的列类型是显式声明的。
注意事项
logical replication slot 的故障转移
materialized_postgresql_replication_slot 设置传入 slot 名称,并且该 slot 必须使用 EXPORT SNAPSHOT 选项导出。快照 标识符则需要通过 materialized_postgresql_snapshot 设置传入。
请注意,只有在确实需要时才应使用这种方式。如果并无实际需求,或者不完全清楚原因,最好让表引擎自行创建和管理 replication slot。
示例 (来自 @bchrobot)
-
在 PostgreSQL 中配置 replication slot。
-
等待 replication slot 就绪,然后开始一个事务并导出该事务的 快照 标识符:
-
在 ClickHouse 中创建数据库:
-
确认已复制到 ClickHouse DB 后,结束 PostgreSQL 事务。验证在故障转移后复制是否仍会继续:
所需权限
- CREATE PUBLICATION — CREATE 查询权限。
- CREATE_REPLICATION_SLOT — 复制权限。
- pg_drop_replication_slot — 复制权限或超级用户权限。
-
DROP PUBLICATION — publication 的所有者 (即 MaterializedPostgreSQL engine 自身中的
username) 。
2 和 3 命令,从而无需具备这些权限。使用设置 materialized_postgresql_replication_slot 和 materialized_postgresql_snapshot 即可。但务必格外谨慎。
对以下表的访问权限:
- pg_publication
- pg_replication_slots
- pg_publication_tables
备份和恢复
MaterializedPostgreSQL 数据库可以备份。每个被复制的表的数据都存放在一个嵌套的 ReplacingMergeTree 表中,因此 BACKUP DATABASE 会通过委托给该嵌套表来备份这些数据。
MaterializedPostgreSQL database 或表原地 restore。恢复后的 MaterializedPostgreSQL object 会立即开始从在线 PostgreSQL source 复制,因此如果在其上恢复 backup snapshot,就会把该 snapshot 与当前远端 state 混在一起。因此,在这种情况下 RESTORE 会以失败并终止的方式安全关闭。请改为将已 capture 的数据恢复到普通的 ReplacingMergeTree 表中:
-
对于 database backup,每个表存储的定义本身已经是合成的嵌套
ReplacingMergeTree(而不是MaterializedPostgreSQLengine) ,因此每个表都可以直接恢复到一个新的、尚不存在的表中: -
对于独立的
MaterializedPostgreSQL表 backup,存储的定义是MaterializedPostgreSQLengine 本身。请预先创建一个ReplacingMergeTree表,使其结构与嵌套表相同 (包括_sign和_version列) ,然后将数据恢复到该表中: