使用 AWS DMS 将 PostgreSQL 数据库迁移至目标 RDS for PostgreSQL 数据库时,应遵循哪些最佳实践?

上次更新日期:2022 年 8 月 29 日

我有一个 PostgreSQL 源数据库,我想将其迁移至目标 Amazon Relational Database Service(Amazon RDS)for PostgreSQL 源数据库。使用 AWS Database Migration Service(AWS DMS)从一个 PostgreSQL 数据库迁移至另一个 PostgreSQL 数据库时,应遵循哪些最佳实践?

简短描述

当使用 AWS DMS 迁移同构数据库时,请使用引擎的原生工具(如 pg_dump)复制初始数据。然后,在目标上执行 pg_restore。您还可以使用逻辑复制和 COPY 命令。有关更多信息,请参阅将 PostgreSQL 数据库迁移至 Amazon RDS 和 Amazon Aurora 的最佳实践

要从 RDS for PostgreSQL 数据库迁移至另一个 RDS for PostgreSQL 数据库,请拍摄快照,然后将快照还原为目标。有关更多信息,请参阅将 RDS for PostgreSQL 数据库实例的快照迁移至 Aurora PostgreSQL 数据库集群

请注意,使用 AWS DMS 在满负载期间将所有数据从源数据库迁移至目标数据库可能需要很长时间。由于以下因素,您可能会遇到延迟:

  • 带宽
  • 推送大量数据的源能力
  • 复制引擎存储、处理和转发批负载的能力
  • 使用源数据的目标容量

相比之下,变更复制只包含从源到目标的更改,因此此类工作负载可能非常轻。

创建并确定当前日志序列号(LSN)

在进行备份之前,您必须获得一个标记,指示您的 AWS DMS 任务从何处开始迁移更改。

在源 PostgreSQL 数据库上,运行这些查询以创建和确定当前的 LSN。

创建复制槽:

SELECT * FROM
pg_create_logical_replication_slot('replication_slot_name','tset_decoding')

获取当前的 LSN:

SELECT restart_LSN  FROM pg_replication_slots WHERE slot_name = 'replication_slot_name';

Restart_LSN 命令告知 AWS DMS 任务从何处开始将更改从源迁至目标。

解决方法

遵循这些最佳实践,通过 AWS DMS 任务将数据从 PostgreSQL 迁移至 PostgreSQL。

满载期间请勿使用外键和触发器

满载时,请确保迁移时不使用外键和触发器。AWS DMS 按字母顺序来迁移表,但不知道哪些是父表,哪些是子表。因此,AWS DMS 可能会尝试先迁移子表。然后,AWS DMS 会因为外键冲突而停止迁移表。因此,在迁移期间,请禁止目标上的外键,或将外键排除在外。

在迁移过程中,触发器绝不可出现在目标上,因为其执行的几个过程可能会损坏目标上的数据。在切换时添加任何触发器。

迁移 JSON 数据时开启完全 LOB 模式

以 JSON 形式迁移 LOB 时,请开启完全 LOB 模式,以免 JSON 格式被截断。如果使用有限 LOB 模式,则可能会发生数据截断。然后,AWS DMS 会确保表失败,因为 JSON 格式错误。

确保主键字段并非 TEXT 数据类型

检查主键字段是否非 TEXT 类型,尤其是在开启完全LOB 模式的情况下。您可能会遇到空值重复的情况,因为 AWS DMS 将 TEXT 数据类型视为 LOB。因此,在满负载期间,AWS DMS 会尝试将主键设为 NULL,然后报告重复,因为存在许多具有相同值的文本列。系统不会将该错误视为“主键不允许 NULL”,而是视为重复。该问题可能难以发现和解决,因此请始终确保您的主键字段并非 TEXT 类型以避免该问题。

允许 AWS DMS 创建目标表

如果是在满负载期间,请允许 AWS DMS 在目标上创建表。当 AWS DMS 创建表时,它还会为列创建不带 DEFAULT 值的匹配字段。列的默认值可能会导致 AWS DMS 中出现异常行为。例如,SERIAL 使 AWS DMS 迁移失败,因为该字段想要自动创建值。请参阅这个例子:

CREATE TABLE COMPANY (
   ID SERIAL PRIMARY KEY,
   NAME TEXT      NOT NULL);

如果目标的结构和此例类似,那么 PostgreSQL 内部需要生成 ID 列的值。但是,该源还包含 INSERT 的值,而这会导致问题。因此,在迁移过程中,请确保 DEFAULTS 并非目标的一部分。

将分区定义为任务表映射上的源表

迁移分区表时,请确保将分区定义为任务表映射上的源表,而非父表。这是因为 WAL 日志会保留分区表信息。父表只能在满负载期间使用,因此不要在 CDC 阶段使用父表。如果在 CDC 期间定义父表,则可能会遇到影响迁移的重复错误。

此外,在映射目标表时,请确保将所有分区重新映射到父表中。这意味着使用父表自动分发到其分区。

使用 PGLOGICAL 时定义源上的所有方面

当您使用 PGLOGICAL 进行迁移时,请确保您已对源上所需的各个方面进行定义。如果跳过某个区域,您将会看到异常行为。由此很难对导致的问题进行故障排除,因此在开始使用 PGLOGICAL 进行迁移之前,请检查是否已定义这些区域。

对于 Amazon RDS,请定义以下项目:

参数组:

shared_preload_libraries = pglocical

数据库级别:

create extension pglogical;

对于本地环境,请定义以下项目:

postgresql.conf:

shared_preload_libraries = pglogical

数据库级别:

create extension pglogical;

确保在源上定义的所有 PG 插件均已在目标上进行定义

确保您在源上定义的所有 PG 插件也已在目标上进行定义。这有助于提高数据的兼容性和顺利处理。

确保任务未处于“停止/错误”状态

当任务很长时间都处于停止或错误状态时,复制槽上的存储空间就会被填满。

从源中删除手动创建的复制槽

如果您手动创建了任何复制槽,请在迁移完成后将其从源中删除。如果复制槽保留在源上,则它们会累积下来,存储空间会被填满。

迁移具有主键/唯一索引的表

最佳实践是确保您要迁移的表具有主键/唯一索引。如果表没有主键,则 UPDATE 和 DELETE 语句可能不会应用于该表,因为其未记录在 WAL 日志中。对于没有主键的表,请使用 REPLICATE IDENTITY FULL,但请注意,这会在日志中生成大量信息。


这篇文章对您有帮助吗?


您是否需要账单或技术支持?