从 PostgreSQL 数据库中流式传输数据

本部分包含有关以下内容的信息:

  • Datastream 如何处理从来源 PostgreSQL 数据库中拉取的数据的行为
  • Datastream 支持的 PostgreSQL 数据库版本
  • 如何设置来源 PostgreSQL 数据库以便将数据从该数据库流式传输到目标位置的概述
  • 将 PostgreSQL 数据库用作来源的已知限制

行为

源 PostgreSQL 数据库依赖其逻辑解码功能。逻辑解码会公开提交到数据库的所有更改,并允许使用输出插件以用户友好的格式使用和处理这些更改。Datastream 使用 pgoutput 插件,这是适用于 PostgreSQL 10 及更高版本的标准 PostgreSQL 逻辑解码插件。

  • 可以选择给定 PostgreSQL 来源中的所有架构或特定架构,以及架构或特定表中的所有表。
  • 复制所有历史数据。
  • 复制所有数据操纵语言 (DML) 变更,例如从指定数据库和表插入、更新和删除。
  • 仅复制已提交的更改。
  • 如果您在表上定义了 REPLICA IDENTITY,Datastream 会将指定的列视为主键。
  • Datastream 会定期向源数据库发送检测信号消息。因此,逻辑解码消息事件 (op:"m") 会直接插入到 WAL 文件中。Datastream 需要这些消息来确保源可用性并计算新鲜度。如果其他复制设置从同一源数据库读取数据,建议您考虑这一点。

版本

Datastream 支持 PostgreSQL 10 及更高版本。

Datastream 支持以下类型的 PostgreSQL 数据库:

  • 自托管的 PostgreSQL
  • Cloud SQL for PostgreSQL
  • AlloyDB for PostgreSQL
  • AlloyDB Omni
  • Amazon RDS for PostgreSQL
  • Amazon Aurora PostgreSQL

最佳做法

本部分介绍了有关配置 PostgreSQL 源以搭配 Datastream 使用的建议最佳实践。

使用多个流来防止队头阻塞

对于 PostgreSQL 源,Datastream 会为整个数据流使用单个逻辑复制槽。如果事务较大,或者对一个高容量表进行多次更新,可能会延迟同一数据流中所有其他表的数据复制。

为防止出现队首阻塞,请为不同的表集创建单独的流。例如,您可以为高容量表创建一个流,为低容量表创建另一个流。这样可以隔离高变动表,防止它们延迟其他表的复制。

建议:找出写入速率极高(INSERT/UPDATE/DELETE)的表,并将它们放置在具有单独复制槽的专用 Datastream 流中。

避免长时间运行的事务

长时间运行的事务可能会导致预写式日志 (WAL) 堆积。由于 WAL 是顺序的,因此即使其他事务正在被使用,PostgreSQL 也无法在长时间事务完成之前刷新 WAL。这可能会增加复制槽大小并减慢逻辑解码速度,因为必须重复解码与当前事务重叠的长时间运行事务中的更改。

建议:在源数据库上,配置 statement_timeoutidle_in_transaction_session_timeout 参数,以避免长时间运行的事务。如需了解详情,请参阅 PostgreSQL 文档

创建出版物时使用表格过滤功能

如果您仅复制少数几个表中的更改,请确保您创建的 PUBLICATION 仅包含这些表。当发布限定为特定表时,PostgreSQL 会高效地仅将这些表中的更改持久保存到复制槽中。这有助于减小复制槽的大小并提高逻辑解码性能。

主动管理复制槽

Datastream 在 PostgreSQL 主实例上使用逻辑复制槽,这可确保 WAL 文件在 Datastream 确认已处理完毕之前一直保留。如果某个流失败、暂停或被删除,但未舍弃复制槽,PostgreSQL 会继续无限期保留 WAL 文件。这可能会导致数据库服务器磁盘空间不足,进而导致生产中断。

建议:在源 PostgreSQL 服务器上设置高效的提醒并监控 WAL 磁盘使用情况。

正确配置副本身份

REPLICA IDENTITY 设置会告知 PostgreSQL 要将哪些数据写入 UPDATEDELETE 事件的 WAL,从而使 Datastream 能够识别哪些行发生了更改。

如果您使用 BigQuery 作为目标,请避免将 REPLICA IDENTITY 设置为 FULL。Datastream 使用记录的列作为 BigQuery MERGE 操作的逻辑键。如果 REPLICA IDENTITY 设置为 FULL,且某个表包含超过 16 列,则会超出 BigQuery 在 MERGE 操作中对主键的 16 列限制,并导致数据流中断。

建议(按偏好程度排序):

  1. 最佳做法:使用主键。REPLICA IDENTITY DEFAULT 的默认设置会自动高效地使用现有的主键。
  2. 良好:如果不存在主键,则创建 UNIQUE NOT NULL 索引并设置 REPLICA IDENTITY USING INDEX INDEX_NAME
  3. 最不推荐:仅在没有唯一标识符的表中使用 REPLICA IDENTITY FULL 设置。如果复制到 BigQuery,请注意性能影响、16 列的限制以及对主键支持的数据类型的限制。

已知限制

将 PostgreSQL 数据库用作来源时,使用 Datastream 的已知限制包括:

  • 数据流限 10,000 个表。
  • 如果表中的行数超过 5 亿,则无法回填,除非满足以下条件:
    1. 相应表具有唯一的 B 树索引。
    2. 索引不包含以下类型的列:DOUBLEFLOATMONEYREALJSONJSONBBYTEATXIDXML复合数据类型几何数据类型
    3. 索引的任何列都不可为 null。
    4. 索引的所有列都按升序排列,或者索引的所有列都按降序排列。
    5. 索引的所有列都包含在流中。
  • 没有主键的表必须具有副本标识。否则,只有 INSERT 事件会被复制到目标。
  • 具有主键的表不能将 REPLICA IDENTITY 设置为 FULLNOTHING。必须将其设置为 DEFAULT
  • Datastream 无法从读取副本实例进行复制,因为 PostgreSQL 不支持读取副本中的逻辑解码。
  • 并非所有对源架构的更改都可以自动检测到,在这种情况下可能会发生数据损坏。以下架构更改可能会导致数据损坏或无法处理下游事件:
    • 删除列。
    • 在表中间添加列。
    • 更改列的数据类型。
    • 对列重新排序。
    • 删除表(如果同一表被重新创建并添加了新的数据,则与此相关)。
  • Datastream 不支持 geometric 数据类型的列。
  • Datastream 不支持 range 数据类型的列。
  • Datastream 不支持以下类型的数组:不支持的数据类型的数组、用户定义的数据类型的数组(包括 ENUM)或 DATETIMESTAMPTIMESTAMP WITH TIME ZONE 数据类型的数组。系统会忽略此类列。
  • 对于在属于表复制身份的列中包含 TOAST 值的行,Datastream 不支持复制 UPDATE 事件。此类事件会被舍弃。
  • Datastream 不支持复制包含超过 2950 个嵌套对象的 JSONJSONB 值的行。包含此类 JSONJSONB 值的事件不会复制到目标数据库。
  • Datastream 不支持复制在 NUMERIC (precision, scale) 列中包含 NaN 值的行。相应列中的值将替换为 NULL 值。
  • Datastream 不支持复制 hstore 数据类型的列。相应列中的值将替换为 NULL 值。
  • Datastream 不支持从 SQL_ASCII 编码的源数据库复制非 ASCII 记录。此类记录会被舍弃。
  • Datastream 不支持复制定义了行级安全性 (RLS) 政策的表。如需了解如何绕过此限制,请参阅 PostgreSQL 来源行为和限制
  • Datastream 不会捕获对生成列所做的更改。
  • 在数据库上执行 PostgreSQL 主要版本升级时,Datastream 可能会停止工作或无法捕获任何新事件。我们建议您在升级之前删除复制槽,然后升级数据库,最后重新创建复制槽。如果数据流失败,请指定新的复制槽名称来恢复数据流,并在需要数据一致性的情况下执行回填。

后续步骤