> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-home-button.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

> ClickPipes for Postgres 常见问题解答。

# ClickPipes for Postgres FAQ

export const Image = ({img, alt, size}) => {
  return <Frame>
      <img src={img} alt={alt} />
    </Frame>;
};

<div id="are-transaction-rollbacks-replicated">
  ### 事务回滚会同步到 ClickHouse 吗？
</div>

不会。CDC (变更数据捕获) 只会复制已提交的事务。已回滚的事务绝不会发送到 ClickHouse。

<div id="retain-data-longer-in-clickhouse">
  ### 我可以让数据在 ClickHouse 中的保留时间比源 Postgres 更长吗？
</div>

可以。源 Postgres 和目标端 ClickHouse 的数据保留策略彼此独立。例如，你可以在 Postgres 中只保留 3 个月的数据，同时在 ClickHouse 中保留完整历史。在 Postgres 中删除旧行会生成会复制到 ClickHouse 的 DELETE 事件，因此如果你想保留历史数据，应在 [publication](/zh/integrations/clickpipes/postgres/faq#ignore-delete-truncate) 中排除 DELETE，或在查询层处理这些事件。

<div id="data-enrichment">
  ### 当数据从 Postgres 流向 ClickHouse 时，如何进行富集？
</div>

在 CDC 目标端表之上使用 [materialized views](/zh/concepts/features/materialized-views)。ClickHouse 中的 materialized view 可充当插入触发器，因此，从 Postgres 复制过来的每一行都可以在写入最终目标表之前进行转换、与查找表关联，或添加额外的列进行富集。

<div id="multi-region-multi-source">
  ### 我可以将多个 Postgres 实例复制到一个或多个 ClickHouse 服务吗？
</div>

可以。您可以从不同的 Postgres 实例 (包括跨 AWS 区域的实例) 分别创建 ClickPipes，并将其接入一个或多个 ClickHouse 服务。例如，您可以将某个区域的 Postgres 数据发送到本地 ClickHouse 集群，以实现低延迟分析；同时发送到另一区域的集中式 ClickHouse 集群，以便进行汇总报表。请注意，跨区域部署会产生 AWS 跨区域数据传输费用，并增加网络延迟。

<div id="how-does-idling-affect-my-postgres-cdc-clickpipe">
  ### 空闲会如何影响我的 Postgres CDC ClickPipe？
</div>

如果你的 ClickHouse Cloud 服务处于空闲状态，Postgres CDC ClickPipe 仍会继续同步数据；服务会在下一个同步间隔到来时唤醒，以处理传入的数据。同步完成后，达到空闲时长后，服务会重新进入空闲状态。

例如，如果同步间隔设置为 30 分钟，而服务空闲时长设置为 10 分钟，那么服务将每 30 分钟唤醒一次并保持活动 10 分钟，然后重新进入空闲状态。

<div id="how-are-toast-columns-handled-in-clickpipes-for-postgres">
  ### ClickPipes for Postgres 如何处理 TOAST 列？
</div>

更多信息，请参阅[TOAST 列处理](/zh/integrations/clickpipes/postgres/toast)页面。

<div id="how-are-generated-columns-handled-in-clickpipes-for-postgres">
  ### ClickPipes for Postgres 如何处理生成列？
</div>

更多信息，请参阅 [Postgres 生成列：注意事项与最佳实践](/zh/integrations/clickpipes/postgres/postgres-generated-columns) 页面。

<div id="do-tables-need-to-have-primary-keys-to-be-part-of-postgres-cdc">
  ### 表要作为 Postgres CDC 的一部分，是否必须有主键？
</div>

要通过 ClickPipes for Postgres 复制表，该表必须定义主键或 [REPLICA IDENTITY](https://www.postgresql.org/docs/current/sql-altertable.html#SQL-ALTERTABLE-REPLICA-IDENTITY)。

* **主键**：最直接的方法是在表上定义主键。主键可为每一行提供唯一标识，这对于跟踪更新和删除至关重要。在这种情况下，可以将 REPLICA IDENTITY 设为 `DEFAULT` (默认行为) 。
* **副本标识**：如果表没有主键，也可以设置副本标识。副本标识可设为 `FULL`，表示使用整行来标识变更。或者，如果表上存在唯一索引，也可以将其设为使用该索引，然后将 REPLICA IDENTITY 设为 `USING INDEX index_name`。
  要将副本标识设为 FULL，可以使用以下 SQL 命令：

```sql theme={null}
ALTER TABLE your_table_name REPLICA IDENTITY FULL;
```

`REPLICA IDENTITY FULL` 还支持复制未发生变化的 TOAST 列。更多信息请参见[此处](/zh/integrations/clickpipes/postgres/toast)。

请注意，使用 `REPLICA IDENTITY FULL` 可能会影响性能，并导致 WAL 增长更快，尤其是对于没有主键且频繁更新或删除的表，因为它需要为每次变更记录更多数据。如果你对为表设置主键或副本标识有任何疑问，或需要相关帮助，请联系我们的支持团队获取指导。

还需注意，如果既未定义主键，也未定义副本标识，ClickPipes 将无法复制该表的变更，并且你可能会在复制过程中遇到错误。因此，建议你在设置 ClickPipe 之前检查表 schema，并确保其满足这些要求。

<div id="do-you-support-partitioned-tables-as-part-of-postgres-cdc">
  ### 是否支持 Postgres CDC 中的分区表？
</div>

是的，支持分区表，开箱即用；前提是已定义 PRIMARY KEY 或 REPLICA IDENTITY。父表及其各个分区都必须包含 PRIMARY KEY 和 REPLICA IDENTITY。你可以在[这里](https://blog.peerdb.io/real-time-change-data-capture-for-postgres-partitioned-tables)了解更多。

<div id="can-i-connect-postgres-databases-that-dont-have-a-public-ip-or-are-in-private-networks">
  ### 我可以连接没有公网 IP 或位于私有网络中的 Postgres 数据库吗？
</div>

可以！ClickPipes for Postgres 提供了两种连接私有网络中数据库的方式：

1. **SSH 隧道**
   * 适用于大多数场景
   * 请在[此处](/zh/integrations/clickpipes/postgres#adding-your-source-postgres-database-connection)查看设置说明
   * 适用于所有区域

2. **AWS PrivateLink**
   * 支持以下三个 AWS 区域：
     * us-east-1
     * us-east-2
     * eu-central-1
   * 详细设置说明请参阅我们的 [PrivateLink 文档](/zh/resources/support-center/knowledge-base/cloud-services/aws-privatelink-setup-for-clickpipes)
   * 如果所在区域不支持 PrivateLink，请使用 SSH 隧道

<div id="how-do-you-handle-updates-and-deletes">
  ### 如何处理 UPDATE 和 DELETE？
</div>

ClickPipes for Postgres 会将来自 Postgres 的 INSERT 和 UPDATE 捕获为 ClickHouse 中带有不同版本的新行 (使用 `_peerdb_` 版本列) 。ReplacingMergeTree 表引擎会基于排序键 (ORDER BY 列) 定期在后台执行去重，仅保留 `_peerdb_` 版本最新的那一行。

来自 Postgres 的 DELETE 会以标记为已删除的新行形式同步过来 (使用 `_peerdb_is_deleted` 列) 。由于去重过程是异步的，你可能会暂时看到重复数据。为此，你需要在查询层处理去重。

另请注意，默认情况下，Postgres 在执行 DELETE 操作时，不会发送不属于主键或副本标识的列值。如果你希望在 DELETE 时捕获完整的行数据，可以将 [REPLICA IDENTITY](https://www.postgresql.org/docs/current/sql-altertable.html#SQL-ALTERTABLE-REPLICA-IDENTITY) 设置为 FULL。

更多详情，请参阅：

* [ReplacingMergeTree 表引擎最佳实践](https://docs.peerdb.io/bestpractices/clickhouse_datamodeling#replacingmergetree-table-engine)
* [Postgres 到 ClickHouse 的 CDC 内部机制博客](https://clickhouse.com/blog/postgres-to-clickhouse-data-modeling-tips)

<div id="can-i-update-primary-key-columns-in-postgresql">
  ### 我可以在 PostgreSQL 中更新主键列吗？
</div>

<Warning>
  默认情况下，PostgreSQL 中对主键的更新无法在 ClickHouse 中被正确回放。

  之所以存在这一限制，是因为 `ReplacingMergeTree` 的去重机制基于 `ORDER BY` 列 (这些列通常对应主键) 。当 PostgreSQL 中的主键发生更新时，在 ClickHouse 中它会表现为一条具有不同键的新行，而不是对现有行的更新。这可能导致旧的和新的主键值同时存在于您的 ClickHouse 表中。
</Warning>

请注意，在 PostgreSQL 数据库设计中，更新主键列并不是常见做法，因为主键本就是为充当不可变标识符而设计的。大多数应用在设计上都会避免更新主键，因此在典型使用场景中很少会遇到这一限制。

有一个 Experimental 设置可用于启用对主键更新的处理，但它会带来显著的性能影响，因此若未经充分评估，不建议在生产环境中使用。

如果您的使用场景需要在 PostgreSQL 中更新主键列，并希望这些变更能够正确反映到 ClickHouse 中，请通过 [db-integrations-support@clickhouse.com](mailto:db-integrations-support@clickhouse.com) 联系我们的支持团队，以讨论您的具体需求和可能的解决方案。

<div id="do-you-support-schema-changes">
  ### 是否支持 schema 变更？
</div>

如需了解更多信息，请参阅 [ClickPipes for Postgres：schema 变更传播支持](/zh/integrations/clickpipes/postgres/schema-changes) 页面。

<div id="what-are-the-costs-for-clickpipes-for-postgres-cdc">
  ### ClickPipes for Postgres CDC 的费用是多少？
</div>

如需了解详细定价信息，请参阅[主计费概览页面中的 ClickPipes for Postgres CDC 定价部分](/zh/products/cloud/reference/billing/clickpipes)。

<div id="my-replication-slot-size-is-growing-or-not-decreasing-what-might-be-the-issue">
  ### 我的 replication slot 大小持续增长或迟迟不下降；可能是什么问题？
</div>

如果你发现 Postgres 的 replication slot 大小持续增加，或始终没有回落，通常意味着**WAL (预写日志，Write-Ahead Log) 记录没有被你的 CDC 管道或复制过程及时消费 (或“重放”) **。下面列出了最常见的原因以及对应的处理方法。

1. **数据库活动突然激增**
   * 大批量更新、批量插入或重大的 schema 变更，都可能在短时间内生成大量 WAL 数据。
   * replication slot 会一直保留这些 WAL 记录，直到它们被消费，因此会导致大小暂时激增。

2. **长时间运行的事务**
   * 一个未结束的事务会迫使 Postgres 保留自该事务开始以来生成的所有 WAL 分段，这可能会显著增大 slot 的大小。
   * 将 `statement_timeout` 和 `idle_in_transaction_session_timeout` 设置为合理的值，以防止事务无限期保持开启状态：
     ```sql theme={null}
     SELECT
         pid,
         state,
         age(now(), xact_start) AS transaction_duration,
         query AS current_query
     FROM
         pg_stat_activity
     WHERE
         xact_start IS NOT NULL
     ORDER BY
         age(now(), xact_start) DESC;
     ```
     使用此查询可识别运行时间异常长的事务。

3. **维护或实用工具操作 (例如 `pg_repack`) **
   * 像 `pg_repack` 这样的工具可能会重写整张表，在短时间内生成大量 WAL 数据。
   * 建议在流量较低的时段安排这类操作，或在其运行期间密切监控 WAL 使用情况。

4. **VACUUM 和 VACUUM ANALYZE**
   * 虽然这些操作对数据库健康必不可少，但它们也会产生额外的 WAL 流量，尤其是在扫描大表时。
   * 可以考虑调整 autovacuum 参数，或将手动执行的 VACUUM 操作安排在低峰时段。

5. **复制消费者未主动读取该 slot**
   * 如果你的 CDC 管道 (例如 ClickPipes) 或其他复制消费者停止、暂停或崩溃，WAL 数据就会在 slot 中不断积累。
   * 请确保你的管道持续运行，并检查日志中是否存在连接或身份验证错误。

如果你想深入了解这个主题，推荐阅读我们的博客文章：[Overcoming Pitfalls of Postgres Logical Decoding](https://blog.peerdb.io/overcoming-pitfalls-of-postgres-logical-decoding#heading-beware-of-replication-slot-growth-how-to-monitor-it)。

<div id="how-are-postgres-data-types-mapped-to-clickhouse">
  ### Postgres 数据类型如何映射到 ClickHouse？
</div>

ClickPipes for Postgres 致力于在 ClickHouse 端尽可能以原生方式映射 Postgres 数据类型。本文档提供了各类数据类型及其映射关系的完整列表：[Data Type Matrix](https://docs.peerdb.io/datatypes/datatype-matrix)。

<div id="can-i-define-my-own-data-type-mapping-while-replicating-data-from-postgres-to-clickhouse">
  ### 在将数据从 Postgres 复制到 ClickHouse 时，我可以自定义数据类型映射吗？
</div>

目前，我们还不支持在管道中自定义数据类型映射。不过需要注意的是，ClickPipes 使用的默认数据类型映射与原生类型高度贴合。Postgres 中的大多数列类型都会尽可能复制为 ClickHouse 中对应的原生类型。例如，Postgres 中的整数数组类型会复制为 ClickHouse 中的整数数组类型。

<div id="how-are-json-and-jsonb-columns-replicated-from-postgres">
  ### Postgres 中的 JSON 和 JSONB 列是如何复制过来的？
</div>

JSON 和 JSONB 列会以 ClickHouse 中的 String 类型进行复制。由于 ClickHouse 原生支持 [JSON 类型](/zh/reference/data-types/newjson)，因此在需要时，您可以基于 ClickPipes 表创建 materialized view 来进行转换。或者，也可以直接对 String 列使用 [JSON 函数](/zh/reference/functions/regular-functions/json-functions)。我们正在积极开发一项功能，可将 JSON 和 JSONB 列直接复制为 ClickHouse 的 JSON 类型，预计会在几个月内推出。

<div id="what-happens-to-inserts-when-a-mirror-is-paused">
  ### 当 mirror 暂停时，insert 会发生什么？
</div>

当你暂停 mirror 时，消息会在源端 Postgres 的 replication slot 中排队，从而确保它们会被缓冲，不会丢失。不过，暂停并恢复 mirror 会重新建立 connection，这可能需要一些时间，具体取决于源端情况。

在此过程中，sync (从 Postgres 拉取数据并将其流式传输到 ClickHouse 原始表) 和 normalize (从原始表到目标表) 操作都会中止。不过，它们会保留可靠恢复所需的状态。

* 对于 sync，如果在中途被取消，Postgres 中的 confirmed\_flush\_lsn 不会前移，因此下一次 sync 会从与已中止任务相同的位置开始，从而确保数据一致性。
* 对于 normalize，ReplacingMergeTree 的 insert 顺序会处理 deduplication。

总之，虽然 sync 和 normalize 进程在暂停期间会终止，但这样做是安全的，因为它们可以在不丢失数据、也不造成不一致的情况下恢复。

<div id="can-clickpipe-creation-be-automated-or-done-via-api-or-cli">
  ### 是否可以自动化创建 ClickPipe，或通过 API 或 CLI 创建？
</div>

也可以通过 [OpenAPI](/zh/products/cloud/features/admin-features/api/openapi) 端点来创建和管理 Postgres ClickPipe。此功能目前处于 Beta 阶段，API 参考文档可在[此处](/zh/api-reference/organization/get-list-of-available-organizations#tag/beta)查看。我们也在积极开发 Terraform 支持，以便创建 Postgres ClickPipes。

<div id="how-do-i-speed-up-my-initial-load">
  ### 如何加快初始加载？
</div>

你无法加快已经在运行的初始加载。不过，可以通过调整某些设置来优化后续的初始加载。默认情况下，系统使用 4 个并行线程，并将每个分区的快照行数设为 100,000。这些属于高级设置，通常已足以满足大多数使用场景。

对于 Postgres 13 及更低版本，CTID 范围扫描速度很慢，因此 ClickPipes 不会使用这种方式。我们会改为将整个表作为单个分区读取，这实际上会变成单线程 (因此会忽略“每个分区的行数”和“并行线程数”这两项设置) 。在这种情况下，如需加快初始加载，你可以增大 `snapshot number of tables in parallel`，或者为大表指定一个自定义且带索引的分区列。

<div id="how-should-i-scope-my-publications-when-setting-up-replication">
  ### 设置复制时，应如何界定 publication 的范围？
</div>

你可以让 ClickPipes 管理 publication (需要额外权限) ，也可以自行创建。使用 ClickPipes 管理的 publication 时，当你编辑管道时，我们会自动处理表的新增和移除。如果选择自行管理，请谨慎界定 publication 的范围，只包含需要复制的表——纳入不必要的表会拖慢 Postgres 的 WAL 解码。

如果在 publication 中包含某张表，请确保该表具有主键或已设置 `REPLICA IDENTITY FULL`。如果某些表没有主键，为所有表创建 publication 会导致这些表上的 DELETE 和 UPDATE 操作失败。

要找出数据库中没有主键的表，可以使用以下查询：

```sql theme={null}
SELECT table_schema, table_name
FROM information_schema.tables
WHERE
    (table_catalog, table_schema, table_name) NOT IN (
        SELECT table_catalog, table_schema, table_name
        FROM information_schema.table_constraints
        WHERE constraint_type = 'PRIMARY KEY') AND
    table_schema NOT IN ('information_schema', 'pg_catalog', 'pgq', 'londiste');
```

处理没有主键的表时，你有两种选择：

1. **将没有主键的表排除在 ClickPipes 之外**：
   创建 publication 时仅包含带有主键的表：
   ```sql theme={null}
   CREATE PUBLICATION clickpipes_publication FOR TABLE table_with_primary_key1, table_with_primary_key2, ...;
   ```

2. **将没有主键的表纳入 ClickPipes**：
   如果你想纳入没有主键的表，需要将其副本标识更改为 `FULL`。这样可确保 UPDATE 和 DELETE 操作正常进行：
   ```sql theme={null}
   ALTER TABLE table_without_primary_key1 REPLICA IDENTITY FULL;
   ALTER TABLE table_without_primary_key2 REPLICA IDENTITY FULL;
   CREATE PUBLICATION clickpipes_publication FOR TABLE <...>, <...>;
   ```

<Tip>
  如果你是手动创建 publication，而不是让 ClickPipes 自动管理，我们不建议创建 `FOR ALL TABLES` 的 publication，因为这会增加从 Postgres 到 ClickPipes 的流量 (会发送管道中未包含的其他表的变更) ，并降低整体效率。

  对于手动创建的 publication，请先将你希望包含的表添加到 publication 中，再将它们添加到管道中。
</Tip>

<Warning>
  如果你是从 Postgres 只读副本/热备库进行复制，则需要自行在主实例上创建 publication，它会自动传播到备用实例。在这种情况下，ClickPipe 无法管理该 publication，因为你不能在备用实例上创建 publication。
</Warning>

<div id="recommended-max_slot_wal_keep_size-settings">
  ### 推荐的 `max_slot_wal_keep_size` 设置
</div>

* **最低建议：** 将 [`max_slot_wal_keep_size`](https://www.postgresql.org/docs/devel/runtime-config-replication.html#GUC-MAX-SLOT-WAL-KEEP-SIZE) 设置为至少保留 **两天**的 WAL 数据。
* **对于大型数据库 (高事务量) ：** 至少保留相当于每日 WAL 峰值生成量 **2-3 倍** 的容量。
* **对于存储受限的环境：** 请谨慎调优该值，在确保复制稳定性的同时**避免磁盘空间耗尽**。

<div id="how-to-calculate-the-right-value">
  #### 如何计算合适的取值
</div>

要确定合适的设置值，请测量 WAL 生成速率：

<div id="for-postgresql-10">
  ##### 对于 PostgreSQL 10 及以上版本
</div>

```sql theme={null}
SELECT pg_wal_lsn_diff(pg_current_wal_insert_lsn(), '0/0') / 1024 / 1024 AS wal_generated_mb;
```

<div id="for-postgresql-96-and-below">
  ##### 对于 PostgreSQL 9.6 及更低版本：
</div>

```sql theme={null}
SELECT pg_xlog_location_diff(pg_current_xlog_insert_location(), '0/0') / 1024 / 1024 AS wal_generated_mb;
```

* 在一天中的不同时间运行上述查询，尤其是在事务量较高的时段。
* 计算每 24 小时产生的 WAL 量。
* 将该数值乘以 2 或 3，以确保有足够的保留空间。
* 将 `max_slot_wal_keep_size` 设置为计算结果对应的 MB 或 GB 数值。

<div id="example">
  ##### 示例
</div>

如果你的数据库每天生成 100 GB WAL，请设置：

```sql theme={null}
max_slot_wal_keep_size = 200GB
```

<div id="im-seeing-a-receivemessage-eof-error-in-the-logs-what-does-it-mean">
  ### 我在日志中看到 ReceiveMessage EOF 错误。这是什么意思？
</div>

`ReceiveMessage` 是 Postgres logical decoding 协议中的一个函数，用于从复制 stream 读取消息。EOF (文件结束) 错误表示，在尝试从复制 stream 读取数据时，与 Postgres server 的连接被意外关闭。

这是一个可恢复、完全非致命的错误。ClickPipes 会自动尝试重新连接并继续复制过程。

这可能由以下几种原因导致：

* **网络问题：** 临时性网络中断可能会导致连接断开。
* **Postgres server 重启：** 如果 Postgres server 重启或崩溃，连接就会丢失。

<div id="my-replication-slot-is-invalidated-what-should-i-do">
  ### 我的 replication slot 已失效，该怎么办？
</div>

恢复 ClickPipe 的唯一方法是触发重新同步，你可以在“设置”页面中执行此操作。

replication slot 失效最常见的原因是 PostgreSQL 数据库中的 `max_slot_wal_keep_size` 设置过低 (例如仅有几 GB) 。我们建议增大该值。关于如何调优 `max_slot_wal_keep_size`，请[参阅本节](/zh/integrations/clickpipes/postgres/faq#recommended-max_slot_wal_keep_size-settings)。理想情况下，应将其至少设置为 200GB，以避免 replication slot 失效。

在极少数情况下，我们发现即使未配置 `max_slot_wal_keep_size`，也会出现此问题。这可能是 PostgreSQL 中某个复杂且罕见的 bug 所致，但具体原因仍不明确。

<div id="i-am-seeing-out-of-memory-ooms-on-clickhouse-while-my-clickpipe-is-ingesting-data-can-you-help">
  ### 当 ClickPipe 正在摄取数据时，我发现 ClickHouse 出现内存不足 (OOM) 。你们能帮忙吗？
</div>

ClickHouse 出现 OOM 的一个常见原因是你的服务规格过小。这意味着你当前的服务配置没有足够的资源 (例如内存或 CPU) 来有效处理摄取负载。我们强烈建议对服务进行扩容，以满足 ClickPipe 数据摄取的需求。

我们观察到的另一个原因，是存在可能包含未优化 JOIN 的下游 materialized views：

* 一种常见的 `JOIN` 优化技巧是：如果你使用了 `LEFT JOIN`，且右侧表非常大，那么可以将查询改写为 `RIGHT JOIN`，并把更大的表移到左侧。这样可以让查询规划器在内存使用上更高效。

* 另一种 `JOIN` 优化方法是，先通过 `subqueries` 或 `CTEs` 显式过滤这些表，再在这些子查询之间执行 `JOIN`。这能为规划器提供提示，从而更高效地过滤行并执行 `JOIN`。

<div id="i-am-seeing-an-invalid-snapshot-identifier-during-the-initial-load-what-should-i-do">
  ### 在初始加载期间看到 `invalid snapshot identifier` 错误，该怎么办？
</div>

当 ClickPipes 与您的 Postgres 数据库之间的连接中断时，就会出现 `invalid snapshot identifier` 错误。这可能是由网关超时、数据库重启或其他暂时性问题导致的。

建议您在初始加载过程中，不要对 Postgres 数据库执行升级、重启等可能造成干扰的操作，并确保与数据库之间的网络连接稳定。

要解决此问题，您可以在 ClickPipes UI 中触发重新同步。这会从头开始重新执行初始加载过程。

<div id="what-happens-if-i-drop-a-publication-in-postgres">
  ### 如果我在 Postgres 中删除了 publication，会发生什么？
</div>

在 Postgres 中删除 publication 会导致你的 ClickPipe 连接中断，因为 ClickPipe 需要依赖该 publication 从源端拉取变更。发生这种情况时，你通常会收到一条错误警报，提示该 publication 已不存在。

要在删除 publication 后恢复 ClickPipe：

1. 在 Postgres 中重新创建一个同名且包含所需表的 publication
2. 点击 ClickPipe 的 Settings 选项卡中的 'Resync tables' 按钮

之所以必须执行这次重新同步，是因为重新创建的 publication 即使名称相同，在 Postgres 中也会拥有不同的对象标识符 (OID) 。重新同步过程会刷新你的目标端表并恢复连接。

或者，如果你愿意，也可以直接新建一个管道。

请注意，如果你处理的是分区表，请务必使用适当的设置来创建 publication：

```sql theme={null}
CREATE PUBLICATION clickpipes_publication
FOR TABLE <...>, <...>
WITH (publish_via_partition_root = true);
```

<div id="what-if-i-am-seeing-unexpected-datatype-errors">
  ### 如果我看到 `Unexpected Datatype` 错误或 `Cannot parse type XX ...`
</div>

当源 Postgres 数据库中存在某种在摄取过程中无法映射的数据类型时，通常会出现此错误。
如需进一步排查，请参阅下面几种可能的情况。

<div id="postgres-invalid-memalloc-bug">
  ### 在复制/slot 创建期间出现类似 `invalid memory alloc request size <XXX>` 的错误
</div>

Postgres 的 17.5/16.9/15.13/14.18/13.21 补丁版本中引入了一个缺陷，某些工作负载可能会导致内存使用量呈指数级增长，进而触发一个超过 1GB 的内存分配请求，而 Postgres 会将其视为无效。该缺陷[已修复](https://github.com/postgres/postgres/commit/d87d07b7ad3b782cb74566cd771ecdb2823adf6a)，并将在下一个 Postgres 补丁系列 (17.6...) 中发布。请向你的 Postgres 提供商确认该补丁版本何时可供升级。如果暂时无法立即升级，则在管道触发此错误时，需要对其执行重新同步。

<div id="ignore-delete-truncate">
  ### 我需要在 ClickHouse 中保留完整的历史记录，即使数据已从源 Postgres 数据库中删除也是如此。我可以在 ClickPipes 中完全忽略来自 Postgres 的 DELETE 和 TRUNCATE 操作吗？
</div>

可以！在创建 Postgres ClickPipe 之前，请先创建一个不包含 DELETE 操作的 publication。例如：

```sql theme={null}
CREATE PUBLICATION <pub_name> FOR TABLES IN SCHEMA <schema_name> WITH (publish = 'insert,update');
```

然后，在为你的 Postgres ClickPipe 进行[设置](/zh/integrations/clickpipes/postgres#configuring-the-replication-settings)时，请确保选择了此 publication 名称。

请注意，ClickPipes 会忽略 TRUNCATE 操作，因此这些操作不会复制到 ClickHouse。

<div id="replicate-table-dot">
  ### 为什么我的表名里有点号就无法复制？
</div>

PeerDB 目前有一个限制：如果 source table 标识符中包含点号——也就是 schema 名称或表名称里带有点号——则不支持复制。因为 PeerDB 会按点号拆分，在这种情况下无法判断哪部分是 schema、哪部分是表。
目前正在尝试通过支持分别输入 schema 和表来规避这一限制。

<div id="initial-load-issue">
  ### 初始加载已完成，但 ClickHouse 中没有数据或数据缺失。可能是什么问题？
</div>

如果初始加载已完成且没有报错，但您的目标端 ClickHouse 表中仍有数据缺失，可能是因为源 Postgres 表启用了 RLS (行级安全) 策略。
还建议检查：

* 该用户是否具有读取源表的足够权限。
* ClickHouse 端是否存在可能过滤掉某些行的行策略。

<div id="failover-slot">
  ### 我可以让 ClickPipe 创建启用了故障转移的 replication slot 吗？
</div>

可以。对于复制模式为 CDC 或 Snapshot + CDC 的 Postgres ClickPipe，你可以在创建 ClickPipe 时，在 `Advanced Settings` 部分打开下方开关，让 ClickPipes 创建启用了故障转移的 replication slot。请注意，使用此功能要求 Postgres 版本为 17 或更高。

<Image img="https://mintcdn.com/private-7c7dfe99-home-button/u7z0gNe6GWCJXTn9/images/integrations/data-ingestion/clickpipes/postgres/failover_slot.png?fit=max&auto=format&n=u7z0gNe6GWCJXTn9&q=85&s=7421c33eca6ec25e133ab87d7a9d4224" border size="md" width="451" height="106" data-path="images/integrations/data-ingestion/clickpipes/postgres/failover_slot.png" />

如果来源端已完成相应配置，那么在故障转移到 Postgres 只读副本后，该 slot 仍会被保留，从而确保数据复制持续进行。更多信息请参见[这里](https://www.postgresql.org/docs/current/logical-replication-failover.html)。

<div id="transient-logical-decoding-errors">
  ### 我遇到了类似 `Internal error encountered during logical decoding of aborted sub-transaction` 的错误
</div>

此错误表明，在对已中止的子事务进行 logical decoding 时出现了暂时性问题，而且这是 Aurora Postgres 自定义实现特有的问题。鉴于错误来自 `ReorderBufferPreserveLastSpilledSnapshot` routine，这说明 logical decoding 无法读取已落盘的快照。可以尝试将 [`logical_decoding_work_mem`](https://www.postgresql.org/docs/current/runtime-config-resource.html#GUC-LOGICAL-DECODING-WORK-MEM) 调高一些。

<div id="logical-message-processing-errors">
  ### 我在 CDC 复制期间看到诸如 `error converting new tuple to map` 或 `error parsing logical message` 之类的错误
</div>

Postgres 会按照固定协议，以消息形式发送变更信息。当 ClickPipe 收到无法解析的消息时，就会出现这类错误，原因可能是传输过程中发生损坏，或发送了无效消息。虽然具体原因各不相同，但我们已经在一些 Neon Postgres 来源中见过多种类似情况。如果你在使用 Neon 时也遇到了这个问题，请向他们提交支持工单。其他情况下，请联系他们的支持团队以获取指导。

<div id="include-excluded-columns">
  ### 我可以纳入最初在复制时排除的列吗？
</div>

目前还不支持此功能。另一种做法是对你想纳入这些列的表[重新同步](/zh/integrations/clickpipes/postgres/table-resync)。

<div id="snapshot-no-data-flow">
  ### 我注意到我的 ClickPipe 已进入 Snapshot，但数据没有流入，可能是什么原因？
</div>

这可能由多种原因导致，主要是执行快照所需的某些前置条件比平时花费更长时间。更多信息，请参阅我们关于并行快照的文档：[见此处](/zh/integrations/clickpipes/postgres/parallel-initial-load)。

<div id="parallel-snapshotting-taking-time">
  #### 并行快照获取分区耗时较长
</div>

并行快照在开始时需要经过几个步骤，以获取表的逻辑分区。如果你的表较小，这一过程通常几秒钟即可完成；但对于非常大的表 (TB 级别) ，则可能需要更长时间。你可以在 **Source** 选项卡中监控 Postgres 源上正在运行的查询，查看是否有与快照获取分区相关的长时间运行查询。分区获取完成后，数据就会开始流入。

<div id="replication-slot-creation-transaction-locked">
  #### Replication slot 创建被事务锁住
</div>

在 Activity 部分下的 **Source** 选项卡中，你会看到 `CREATE_REPLICATION_SLOT` 查询卡在 `Lock` 状态。这可能是因为另一个事务持有了 Postgres 在创建 replication slot 时使用的对象锁。
要查看造成阻塞的查询，你可以在 Postgres 源上运行以下查询：

```sql theme={null}
SELECT
  blocked.pid AS blocked_pid,
  blocked.query AS blocked_query,
  blocking.pid AS blocking_pid,
  blocking.query AS blocking_query,
  blocking.state AS blocking_state
FROM pg_locks blocked_lock
JOIN pg_stat_activity blocked
  ON blocked_lock.pid = blocked.pid
JOIN pg_locks blocking_lock
  ON blocking_lock.locktype = blocked_lock.locktype
  AND blocking_lock.database IS NOT DISTINCT FROM blocked_lock.database
  AND blocking_lock.relation IS NOT DISTINCT FROM blocked_lock.relation
  AND blocking_lock.page IS NOT DISTINCT FROM blocked_lock.page
  AND blocking_lock.tuple IS NOT DISTINCT FROM blocked_lock.tuple
  AND blocking_lock.virtualxid IS NOT DISTINCT FROM blocked_lock.virtualxid
  AND blocking_lock.transactionid IS NOT DISTINCT FROM blocked_lock.transactionid
  AND blocking_lock.classid IS NOT DISTINCT FROM blocked_lock.classid
  AND blocking_lock.objid IS NOT DISTINCT FROM blocked_lock.objid
  AND blocking_lock.objsubid IS NOT DISTINCT FROM blocked_lock.objsubid
  AND blocking_lock.pid != blocked_lock.pid
JOIN pg_stat_activity blocking
  ON blocking_lock.pid = blocking.pid
WHERE NOT blocked_lock.granted;
```

一旦定位到阻塞查询，你可以选择等待其完成；如果它不重要，也可以将其取消。阻塞查询解除后，replication slot 的创建应会继续，这样 snapshot 就能开始，数据也会流入。
