亚马逊AWS官方博客

同构跨云 / IDC 的 PostgreSQL 迁移工程化实践——当源库含触发器、无主键 LOB 表等情况时,用一套可复用脚本 + AWS DMS 完成完整、一致的迁移

摘要:PostgreSQL 是使用最广泛的开源关系型数据库之一,其同构(同引擎)跨云或上云迁移常用 AWS Database Migration Service(AWS DMS)完成。AWS DMS 提供“转换或迁移至托管”(同构数据迁移)和“迁移和复制”两种方式。本项目采用“转换或迁移至托管”的同构迁移方式,并配合一套脚本预建目标库结构、处理触发器、迁移后补齐次级对象与校验一致性来完成。本文面向需要近实时同步、最小停机,且源库不满足 AWS DMS 直接完整迁移前提的团队:包括迁移前置准备(源库备份、测试环境验证)、用脚本自动生成迁移所需 SQL 与执行清单、AWS DMS 同构迁移任务配置、迁移后次级对象补齐与一致性校验。方案的核心思路与关键配置(如源库必须设置 REPLICA IDENTITY FULL)在 AWS DMS “迁移和复制” 方式下同样验证通过,故也可作为该方式的参考(本文不展开)。本文提供完整方案代码与逐步操作说明,并经过实际项目实施验证。


一、引言

在企业将自建(IDC/Amazon EC2)或其他云平台上的 PostgreSQL 迁移到亚马逊云科技(Amazon Web Services)的过程中,数据库迁移往往是风险最高的一环:既要数据零丢失、把停机窗口压到最小,又要确保源库与目标库在表结构、索引、约束、触发器、序列、默认值以及大对象(LOB)列上完全一致。

Amazon Database Migration Service(Amazon DMS)针对同引擎(同构)PostgreSQL 迁移提供两种方式,如下简介,但直接使用亚马逊云科技控制台或 AWS CLI 命令执行迁移都有其前提条件和约束。在 Amazon DMS 直接适用时(如源库结构标准、无触发器、所有含 LOB 列的表均有主键等),可直接使用 Amazon DMS “转换或迁移至托管”完成同构迁移,本文不进行展开,有需要时可参考官方文档。

DMS 方式 能力
转换或迁移至托管 (Homogeneous data migration) 基于原生工具(pg_dump/pg_restore/pglogical),可迁移数据及索引、外键、触发器、函数等次级对象
迁移和复制 (Migrate and replicate) 支持异构数据库的迁移;复制实例上的 Full Load + CDC,源库可在线,实现近实时同步与最小停机切换;默认只迁移数据与主键

本文以一次同构 PostgreSQL 迁移项目的实践为基础(源库为其他云托管、含触发器等不满足 Amazon DMS 直接完成迁移的情形,目标为 Amazon RDS for PostgreSQL),将在项目实施过程中提炼并实际使用验证过的方案分享给大家。并对其中的核心脚本 generate_migration_scripts.sh,及脚本生成的 RUN_ORDER.md 如何与 Amazon DMS 同构迁移(“转换或迁移至托管”)控制台配置一起协同完成迁移进行展开说明。

二、适用场景与方案选择

Amazon DMS 针对同引擎(同构)PostgreSQL 迁移提供“转换或迁移至托管”(同构数据迁移)和“迁移和复制”两种方式。在源库结构标准、符合 Amazon DMS 前提条件的情况下,推荐直接使用“转换或迁移至托管”完成迁移,无需额外脚本。但当源库存在触发器、或含无主键的 LOB 表等不满足 Amazon DMS 直接迁移前提的情况时,需要配合脚本辅助或采用其他手工方案。本文是后一种情况,并且生产环境 24 小时运作、要求最小停机。

在不能(或不完全)使用 Amazon DMS “转换或迁移至托管”控制台一键完成的情形下(例如源库含触发器、无主键 LOB 表),常见的替代方案如下,下表简要对比它们在停机时间、次级对象完整性、操作复杂度上的取舍:

方案 停机时间 次级对象(索引/外键/触发器/序列) 操作复杂度与问题
pg_dump / pg_restore(全手工) 停机时间长:导出+导入全程需源库停写,数据越大停机越久 ✓ 唯一可完整迁移次级对象的原生工具 速度最慢;dump 文件可能远大于原表;大库需手工拆表/并行/调参;切换前无法追增量
逻辑复制(publisher/subscriber 或 pglogical,手工) 停机时间短:可边同步边追增量,但需自行搭建与运维复制链路 ✗ 不迁移视图/存储过程/触发器等,需另行手工 schema dump 补齐 配置复杂:需改 wal_level、pg_hba.conf、重启实例、手建 publication/subscription;无主键表 CDC 困难
本方案:Amazon DMS 同构迁移(“转换或迁移至托管”) + 脚本 ✅ 最小停机:全量+CDC 近实时同步,源库全程在线,停机仅为最后切换的分钟级窗口 ✓ 脚本自动预建结构、迁移后补齐索引/外键/触发器/序列并校验 Amazon DMS 托管迁移环境(无服务器、自动伸缩);脚本一键生成,解决触发器/无主键 LOB 难题

全手工 pg_dump/pg_restore 能保完整性但停机长、大库慢;手工逻辑复制停机短但不管次级对象、配置繁琐。本方案用 DMS 同构迁移(全量+CDC)保障“最小停机”,再用一套可复用脚本自动处理触发器、无主键 LOB 与次级对象补齐,在满足完整一致性的同时将停机窗口压到最小。

本文的项目场景下源库存在触发器(加载时被触发会导致记录不一致)、含 text/jsonb 大字段但无主键/唯一约束,如果直接使用 Amazon DMS “转换或迁移至托管”无法保证完整一致性。本文方案通过脚本预建目标库结构、禁用触发器、迁移后补齐次级对象,配合同构迁移顺利完成。

在数据库停机时间方面,项目需要最小停机,业务系统不能长时间中断,要求切换停机窗口尽可能短。Amazon DMS 同构迁移支持全量加载 + 增量同步(CDC),本方案在实施时结合 Amazon DMS 的特性进行方案设计,源库在全量与追增量期间保持在线可写,停机窗口仅为最后“停写 → 等增量追平 → 校验 → 切换”这一小段(通常分钟级)。

另外,Amazon DMS 的“迁移和复制”(经典复制任务)也可配合本文方案的脚本完成迁移(核心思路与关键配置已验证通过),本文不再展开其详细控制台配置。对于迁移的源与目标,本方案的源端支持自建(IDC / Amazon EC2)、其他公有云托管的 PostgreSQL、以及亚马逊云科技其他区域/账号的 PostgreSQL;目标端为 Amazon RDS for PostgreSQL 或 Amazon Aurora PostgreSQL。

三、整体架构

下图展示了本方案的整体架构。迁移在三个逻辑区域间进行:源环境(自建 / 其他云)、迁移与自动化层(Amazon DMS 同构迁移“转换或迁移至托管” + 脚本套件)、目标环境(亚马逊云科技)。

[图 1:同构 PostgreSQL 迁移到 Amazon RDS for PostgreSQL 的整体架构]

如图 1 所示,架构分为三个区域。源环境(自建或其他云托管的 PostgreSQL)开启逻辑复制(wal_level=logical)并对所有表设置 REPLICA IDENTITY FULL,使增量阶段能捕获完整行变更。迁移与自动化层 以 Amazon DMS 同构迁移(“转换或迁移至托管”)负责数据迁移,配合脚本套件在 Amazon DMS 之外完成目标库结构预建、触发器禁用与恢复、序列重置与一致性校验。目标环境 为 Amazon RDS for PostgreSQL(目标库);图中的 Amazon EC2 是运行迁移脚本(.sh 与 psql)的临时服务器 / 跳板机,需与源库、目标库网络互通。数据流向为:源库 → Amazon DMS 全量加载 + 增量同步 → 目标库;脚本从这台 Amazon EC2 上连接源/目标库,在 Amazon DMS 加载前后分别介入,补齐 Amazon DMS 默认不迁移的次级对象。业务应用层的迁移按实际情况进行,与本文聚焦的数据库迁移相对独立,此处不展开。

四、前提条件

项目 要求
亚马逊云科技账户 具备创建 Amazon DMS、Amazon RDS、VPC/安全组 的 IAM 权限;Amazon DMS 需访问 Secrets Manager 的权限
源库 PostgreSQL 可开启逻辑复制(自建库 wal_level=logical;托管 RDS 类源库对应 rds.logical_replication=1);网络可被 Amazon DMS 访问(建议 VPN/专线)
目标库 已创建 Amazon RDS for PostgreSQL 实例,版本 ≥ 源库主版本;自定义参数组开启 rds.logical_replication
客户端 / 跳板机 Amazon Linux 2023 + psql、pg_dump(PostgreSQL 17 客户端),与 Amazon DMS 同 VPC,用于运行脚本

源库必须设置 REPLICA IDENTITY FULL:这是 CDC 阶段能正确捕获 UPDATE/DELETE 完整行(含 TOAST/大字段列)的关键,尤其是无主键表。例如如下 sql 为迁移前对源库前提条件的核对的一部分,查询含 LOB 列 (text/jsonb/json) 且无主键的表:

SELECT 
    c.table_name,
    string_agg(DISTINCT c.column_name || ' (' || c.data_type || 
        CASE WHEN c.is_nullable = 'NO' THEN ', NOT NULL' ELSE '' END || ')', 
        ', ' ORDER BY c.column_name || ' (' || c.data_type || 
        CASE WHEN c.is_nullable = 'NO' THEN ', NOT NULL' ELSE '' END || ')'
    ) AS lob_columns,
    (SELECT COUNT(*) FROM information_schema.columns c2 
     WHERE c2.table_schema = 'public' AND c2.table_name = c.table_name) AS total_columns
FROM information_schema.columns c
WHERE c.table_schema = 'public'
  AND c.data_type IN ('text', 'jsonb', 'json')
  AND c.table_name NOT LIKE 'awsdms%'
  AND NOT EXISTS (
    SELECT 1 FROM information_schema.table_constraints tc
    WHERE tc.table_schema = 'public'
      AND tc.table_name = c.table_name
      AND tc.constraint_type = 'PRIMARY KEY'
  )
GROUP BY c.table_name
ORDER BY c.table_name;
⚠️ 关于源库参数与 REPLICA IDENTITY FULL
修改 wal_level / rds.logical_replication(视源库形态而定)通常会重启数据库,生产环境请安排在维护窗口执行。REPLICA IDENTITY FULL 会增加 WAL 体积,属正常现象——脚本会自动为源库全表生成设置语句(见下文 00 脚本)。

五、迁移前置准备与前后要点

正式迁移前的准备工作,往往比迁移动作本身更能决定成败。本项目在进入 RUN_ORDER 执行前,先完成了以下前置动作,并在切换前后设置了明确的检查点。

5.1 迁移前对源库做完整备份

无论采用哪种迁移方式,动手前必须先对源库做一次完整、可恢复的备份,作为最终的兜底手段:

  • 托管 RDS 类源库:先创建一个手动快照(Snapshot),确认状态为 available 后再开始;必要时导出到对象存储长期留存。
  • 自建 / IDC 源库:用 pg_dump 做一次逻辑备份(或结合物理备份),并验证备份可成功恢复到一个临时实例,避免“备份了但恢复不出来”。
  • 记录基线:备份完成后记录源库的对象与行数基线(可直接用脚本生成的 05_verify.sql 在源库跑一遍),作为迁移后一致性比对的“标准答案”。
为什么强调备份可恢复
REPLICA IDENTITY FULL、参数组修改等前置操作可能触发源库重启;CDC 与切换过程中也存在误操作风险。一份经过恢复验证的备份,是出现意外时能够回到原点的前提。

5.2 先在测试环境完整演练,再上生产

生产迁移前,务必在测试环境按相同流程完整演练一遍。本项目正是先在测试库跑通全流程、并用对比脚本发现并修正了次级对象缺失问题(见后文真实截图),才进入生产迁移:

  1. 搭建等价测试环境:用源库备份/快照还原出一套测试源库与目标库,规格可等比缩小,但 PostgreSQL 版本、扩展、schema 需与生产一致。
  2. 全流程演练:在测试环境完整执行 RUN_ORDER 的 Step 0–7 与 Amazon DMS 同构迁移任务,记录各阶段耗时(数据加载时长、增量追平时间),用于估算生产停机窗口。
  3. 一致性校验演练:用 05_verify.sql 对比测试源库与目标库,确认脚本能把索引/约束/触发器/序列/默认值/LOB 全部补齐后再上生产。
  4. 应用连通性演练:让应用以只读或灰度方式连接测试目标库,验证连接串、权限(例如 app_user 等应用连接使用的数据库用户的权限)、扩展依赖是否齐全。

5.3 切换前后的检查要点

时机 时机 检查要点
切换前 切换前 源库备份已完成且验证可恢复;测试环境演练通过;目标库结构/扩展/权限就绪;发布维护通知;确认回滚触发条件与责任人
停写与追平 停写与追平 停止源库写入;确认无业务连接(查询 pg_stat_activity 仅剩 Amazon DMS);等待 CDC 追平(延迟归零)
切换中 切换中 执行 03/04 补齐对象与序列;运行 05_verify.sql 逐项比对源/目标一致;应用回归测试通过
切换后 切换后 监控应用与数据库指标(连接数、慢查询、错误日志);保留源库只读一段时间;确认稳定后再停止 Amazon DMS 任务并清理临时资源
回滚预案
预先约定回滚触发条件(如切换后核心业务不可用、数据一致性出现严重问题、性能明显退化)。回滚时切回源库连接串即可——这也是切换前保留源库只读、不立即下线的意义所在。

六、方案概览

迁移流程对应脚本生成的执行清单 RUN_ORDER 的 Step 0 至 Step 7,如图 3 所示。脚本生成的 SQL 与 Amazon DMS 同构迁移任务协同工作,把停机窗口压缩到“停源库写入 → 停增量同步 → 校验 → 切换应用”这一小段时间内。

[图 2:迁移端到端执行流程(对应 RUN_ORDER 的 Step 0–7)]

如图 3 所示,流程分为四个阶段。准备阶段(Step 0–3)在源库设置逻辑复制与全表 REPLICA IDENTITY FULL,并在目标库预建表结构、禁用触发器、创建 Amazon DMS 辅助表;迁移阶段(Step 4)配置并启动 Amazon DMS 同构迁移任务(全量 + 增量),源库保持在线;追平阶段(Step 5)停源库写入、停增量同步并补齐索引与约束;收尾阶段(Step 6–7)重置序列、恢复触发器、执行一致性校验后切换应用。这里要特别说明:源库全表设置 REPLICA IDENTITY FULL 后,增量阶段可捕获完整行,含 LOB 列的表在此前提下无需额外的临时主键处理(这与早期版本脚本不同,v5 已不再包含单独的 LOB 修复步骤)。

七、迁移脚本套件的实现与做法

为解决“源库含触发器/无主键 LOB 表时,Amazon DMS 同构迁移需要额外前后处理”的问题,本项目实践中编写了一个脚本 generate_migration_scripts.sh,用于把迁移前后要在源/目标库执行的 SQL 固化下来。脚本连接源库,一次性生成迁移全过程所需的 SQL、Amazon DMS 任务配置参考,以及一份执行清单 RUN_ORDER.md。

从技术实现看,脚本的 SQL 均从源库系统目录(information_schema / pg_catalog)动态查询生成,不写死表名,因此与具体表结构无关、可随 Schema 变更重复运行再生。对读者的借鉴意义在于:它把一次迁移中容易遗漏的次级对象(索引、外键、约束、序列、触发器、默认值)和执行顺序沉淀为可复用的生成逻辑,便于在类似的同构 PostgreSQL 迁移中直接套用或二次开发,减少手工梳理与遗漏。

脚本产出的文件

文件 作用 执行时机
00_set_source_db_identity_full.sql 源库全表设置 REPLICA IDENTITY FULL 迁移前(源库)
01_pre_data.sql 目标库预建表结构、序列、默认值、函数 Full Load 前(目标库)
02_pre_dms_disable_triggers.sql 禁用触发器 + session_replication_role=replica Full Load 前(目标库)
03_post_data.sql 创建索引、外键、CHECK、UNIQUE、触发器 Full Load 后(目标库)
04_post_dms_restore.sql 重置序列、重新启用触发器、ANALYZE Full Load 后(目标库)
05_verify.sql 校验表数/行数/索引/序列/触发器/约束/LOB 迁移后(源与目标对比)
dms_task_config_reference.json Amazon DMS 任务关键配置参考 创建 Amazon DMS 任务时
RUN_ORDER.md 自动生成的执行顺序清单 全程照做

实现要点 1:源库全表设置 REPLICA IDENTITY FULL(00 脚本)

# 从源库动态生成全表 REPLICA IDENTITY FULL 语句
psql -h "$SRC_HOST" -U "$SRC_USER" -d "$SRC_DB" -t -A -c "
  SELECT 'ALTER TABLE ' || table_schema || '.' || table_name
         || ' REPLICA IDENTITY FULL;'
  FROM information_schema.tables
  WHERE table_schema NOT IN ('pg_catalog','information_schema')
    AND table_type = 'BASE TABLE';
" >> "$OUTPUT_DIR/00_set_source_db_identity_full.sql"

实现要点 2:用 pg_dump 分段导出 Schema

用 pg_dump 的 –section 把 Schema 拆成 pre-data(表结构/序列/默认值/函数)与 post-data(索引/约束/触发器)两段,精准对应 Amazon DMS 加载前后:

# pre-data:Amazon DMS 加载前在目标库建好(表、序列、默认值、函数)
pg_dump -h "$SRC_HOST" -U "$SRC_USER" -d "$SRC_DB" \
    --schema-only --section=pre-data \
    --no-owner --no-privileges --no-tablespaces \
    -f "$OUTPUT_DIR/01_pre_data.sql"
 
# post-data:Amazon DMS 加载后再建(索引、外键、CHECK、UNIQUE、触发器)
pg_dump -h "$SRC_HOST" -U "$SRC_USER" -d "$SRC_DB" \
    --schema-only --section=post-data \
    --no-owner --no-privileges --no-tablespaces \
    -f "$OUTPUT_DIR/03_post_data.sql"

实现要点 3:自动生成序列重置语句(04 脚本)

Full Load 后目标库序列 last_value 不会自动对齐,新写入会主键冲突。脚本反查“序列→列”归属,自动生成 setval:

psql -h "$SRC_HOST" -U "$SRC_USER" -d "$SRC_DB" -t -A -c "
  SELECT 'SELECT setval(''' || n.nspname || '.' || s.relname || ''',
      COALESCE((SELECT MAX(' || a.attname || ') FROM '
      || n2.nspname || '.' || c.relname || '), 1));'
  FROM pg_class s
  JOIN pg_namespace n  ON n.oid = s.relnamespace
  JOIN pg_depend d     ON d.objid = s.oid
  JOIN pg_class c      ON c.oid = d.refobjid
  JOIN pg_namespace n2 ON n2.oid = c.relnamespace
  JOIN pg_attribute a  ON a.attrelid = c.oid AND a.attnum = d.refobjsubid
  WHERE s.relkind = 'S' AND d.deptype = 'a'
    AND n.nspname NOT IN ('pg_catalog','information_schema');
" >> "$OUTPUT_DIR/04_post_dms_restore.sql"

八、RUN_ORDER 详细执行步骤

脚本执行完成后会生成 RUN_ORDER.md。实际迁移就是“照着 RUN_ORDER 执行脚本”与“在 Amazon DMS 控制台配置同构迁移(“转换或迁移至托管”)任务”两条线协同推进。如下真实项目的截图实例,接下来以示例值结合实际项目实施的截图展开说明。

[图 3:脚本生成的 RUN_ORDER 实例]

生成的 RUN_ORDER.md 已把源库、目标库的连接信息填充为实际值,可直接复制执行。以下为一份示例(连接地址、库名等按实际环境替换):

# 执行顺序
# 前提: 已设置源库 wal 参数;已创建目标库并配置自定义参数组;Amazon DMS 迁移任务已创建
 
# Step 0: 设置源库 REPLICA IDENTITY FULL
psql -h 10.0.1.20 -p 5432 -U postgres -d appdb \
     -f 00_set_source_db_identity_full.sql
 
# Step 1: 清空目标库(如需,需对所有 schema 执行)
# 直接删除并重建目标数据库最快,或逐个删除 schema
 
# Step 2: 创建表结构(序列 / 默认值 / 函数)
psql -h mytarget.abcdefg.us-east-1.rds.amazonaws.com -p 5432 -U postgres -d appdb \
     -v ON_ERROR_STOP=1 -f 01_pre_data.sql
 
# Step 3: 禁用触发器
psql -h mytarget.abcdefg.us-east-1.rds.amazonaws.com -p 5432 -U postgres -d appdb \
     -f 02_pre_dms_disable_triggers.sql
 
# Step 3.5: 创建Amazon DMS 过程表及授权
psql -h mytarget.abcdefg.us-east-1.rds.amazonaws.com -p 5432 -U postgres -d appdb \
     -f ../DMS-use-tables.sql
 
# Step 4: 启动Amazon DMS 同构迁移任务(参考 dms_task_config_reference.json)
#   等待全量加载完成 → 开始增量(CDC) → 验证行数与增量结果
 
# Step 5: 创建索引、约束、触发器
psql -h mytarget.abcdefg.us-east-1.rds.amazonaws.com -p 5432 -U postgres -d appdb \
     -f 03_post_data.sql
 
# Step 6: 重置序列、启用触发器、ANALYZE
psql -h mytarget.abcdefg.us-east-1.rds.amazonaws.com -p 5432 -U postgres -d appdb \
     -f 04_post_dms_restore.sql
 
# Step 7: 一致性校验(源库与目标库分别执行并比对)
psql -h mytarget.abcdefg.us-east-1.rds.amazonaws.com -p 5432 -U postgres -d appdb \
     -f 05_verify.sql
 
# 后续: 切换应用连接、应用回归测试、停止 Amazon DMS 任务
说明
上例中 10.0.1.20(源库)、mytarget.abcdefg.us-east-1.rds.amazonaws.com(目标 Amazon RDS 终端节点)、appdb 等均为占位示例,请替换为实际环境的连接信息。RUN_ORDER.md 由脚本按“配置区”的取值自动填充生成,无需手工拼接命令。

8.1 Step 0:源库设置 REPLICA IDENTITY FULL

# Step 0: 设置源库 REPLICA IDENTITY FULL
psql -h 10.0.1.20 -p 5432 -U postgres -d appdb \
     -f 00_set_source_db_identity_full.sql

确保源库开启逻辑复制且全表 REPLICA IDENTITY FULL,保证 CDC 阶段 UPDATE/DELETE 捕获完整行。

8.2 Step 1–3:目标库预建结构、禁用触发器、创建 Amazon DMS 辅助表

# Step 1: 清空目标库(如需,需对所有 schema 执行)
# 直接删除并重建目标数据库最快,或逐个删除 schema
 
# Step 2: 创建表结构(序列 / 默认值 / 函数)
psql -h mytarget.abcdefg.us-east-1.rds.amazonaws.com -p 5432 -U postgres -d appdb \
     -v ON_ERROR_STOP=1 -f 01_pre_data.sql
 
# Step 3: 禁用触发器
psql -h mytarget.abcdefg.us-east-1.rds.amazonaws.com -p 5432 -U postgres -d appdb \
     -f 02_pre_dms_disable_triggers.sql
 
# Step 3.5: 创建 Amazon DMS 过程表及授权
psql -h mytarget.abcdefg.us-east-1.rds.amazonaws.com -p 5432 -U postgres -d appdb \
     -f ../DMS-use-tables.sql
关键:为什么要禁用触发器
源库含触发器时,若不禁用,Amazon DMS 灌数据会触发审计/校验/时间戳等业务触发器,污染数据、导致记录不一致。这正是本场景不能“开箱即用”地跑 “转换或迁移至托管” 的原因——必须先在目标库预建结构并禁用触发器,再由 DMS 同构迁移灌数据,之后恢复触发器。

8.3 Step 4:在 Amazon DMS 控制台配置并启动同构迁移任务

在 Amazon DMS 控制台选择“转换或迁移至托管”,通过“数据提供程序 → 迁移项目 → 数据迁移任务”三步创建同构迁移。首先创建源与目标两个数据提供程序,其中 Purpose 选择 Move to managed(Homogeneous data migrations),引擎类型为 PostgreSQL。图 4 展示了创建源数据提供程序的界面。

[图 4:创建数据提供程序——Purpose 选择“Move to managed(Homogeneous data migrations)”,引擎为 PostgreSQL(真实项目)]

图 4 中,数据提供程序的名称需符合命名规则;Purpose 选择右侧的 Move to managed 即表示走同构数据迁移路径;引擎配置可选择“RDS 数据库实例”(目标库)或“手动输入”(填写源库地址/端口等)。凭证建议统一用 AWS Secrets Manager 托管,创建迁移项目时按密钥 ARN 引用。

创建迁移项目并绑定源/目标数据提供程序后,在项目下创建数据迁移任务。迁移类型选择 Full load and change data capture (CDC)(全量 + 持续增量),并开启 CloudWatch 日志。图 5 展示了迁移类型的选择界面。

[图 5:数据迁移任务——迁移类型选择“Full load and change data capture (CDC)”,并开启 CloudWatch 日志(真实项目)]

如图 5 所示,界面提示“执行全量迁移时,目标库上的所有数据、表和其他对象将被删除,请确保已备份目标库”——这与本文“迁移前先备份、先在测试环境演练”的要点一致。表映射(Selection rules)用 JSON 设置为包含全部 schema 与表、排除 awsdms_% 辅助表;Stop mode 选择 Do not stop CDC,由 Amazon DMS 持续增量同步,切换前再手动停止。

{
  "rules": [
    { "rule-type": "selection", "rule-id": "1",
      "rule-name": "include-all-tables", "rule-action": "include",
      "object-locator": { "schema-name": "%", "table-name": "%" } }
  ]
}

触发器处理(关键):因源库含触发器,需先执行脚本 01/02 在目标库预建结构并禁用触发器(session_replication_role=replica),再启动同构迁移灌数据,迁移后用 03/04 恢复。这样即使采用同构迁移,也不会因触发器在加载时被触发而产生记录不一致。

检查全部配置无误后启动迁移任务。图 6 展示了启动数据迁移的确认界面,其中再次提示“全量迁移会删除目标库现有对象,请确保已备份”。

[图 6:启动数据迁移的确认界面,并提示确保已备份目标库(真实项目截图)]

[图 7:迁移完成后,进入 CDC 持续增量同步]

[图 8:到达切换时点,停止迁移任务(停止 CDC 增量同步)]

上述步骤在生产环境执行时,可以提前执行,直到切换生产环境的时间窗口到达,才停止 CDC 增量同步和源库写入。

脚本关键配置在两种方式下均适用
源库必须设置 REPLICA IDENTITY FULL(脚本 00 自动生成)是保证增量阶段正确捕获 UPDATE/DELETE 完整行的关键。此配置与脚本的核心思路(预建结构、禁用/恢复触发器、补齐次级对象、一致性校验)在Amazon DMS “迁移和复制”(经典复制任务)方式下同样验证通过,因此本文脚本亦可作为该方式的参考——限于篇幅,本文不展开“迁移和复制”的具体控制台配置。

8.4 Step 5–6:数据加载完成后补齐对象

在 Amazon DMS 控制台显示全量加载完成、增量追平后,停止源库写入并停止增量同步,然后补齐 post-data 与序列:

# Step 5: 创建索引、约束、触发器
psql -h mytarget.abcdefg.us-east-1.rds.amazonaws.com -p 5432 -U postgres -d appdb \
     -f 03_post_data.sql

# Step 6: 重置序列、启用触发器、ANALYZE
psql -h mytarget.abcdefg.us-east-1.rds.amazonaws.com -p 5432 -U postgres -d appdb \
     -f 04_post_dms_restore.sql

[图 9:Step 5-6 运行的截图示例]

8.5 Step 7:一致性校验与切换

psql -h mytarget.abcdefg.us-east-1.rds.amazonaws.com -p 5432 -U postgres -d appdb -f 05_verify.sql

在源库与目标库分别运行 05_verify.sql 并逐项比对(表数/行数/索引/序列/触发器/约束/LOB 非空行数)。全部一致后,切换应用连接串、做应用回归测试,最后停止 Amazon DMS 任务。

说明:05_verify.sql 只比较了通用数据和对象,如果有业务数据关系等比较,强烈推荐根据业务和数据库特性增加校验。

九、生产环境迁移实施的其他建议

对于生产环境的迁移,在前述方案和要点的基础上,从可用性和安全等方面还有如下建议推荐实际迁移时考虑:

  • 高可用:Amazon RDS for PostgreSQL 启用 Multi-AZ,或采用 Amazon Aurora PostgreSQL;Amazon DMS 复制实例生产环境时使用多可用区。
  • 凭证管理:源/目标数据库口令统一用 AWS Secrets Manager 托管(创建数据提供程序时可直接选用密钥 ARN),避免明文写入脚本。
  • 最小权限:为执行的 Amazon EC2 配置最小权限的 IAM Role 权限,为应用创建独立 数据库连接用户(如 app_user) 并按 schema 精细授权等遵从最小授权原则进行测试和生产环境迁移。
  • 网络:Amazon DMS 与源/目标库尽量走私有网络(VPN/专线/对等连接);通过公网迁移时严格限制安全组来源 IP。
  • 回滚预案:切换前保留源库只读一段时间,CDC 断开后如发现问题可快速回切。

十、方案脚本参考和说明

本方案的完整内容参见仓库。下面是核心脚本,在使用时只需修改顶部“配置区”的源/目标连接信息,运行后按生成的 RUN_ORDER.md 执行即可。

generate_migration_scripts.sh

#!/bin/bash
# 通用Amazon DMS 迁移脚本生成器:自动从源库导出 pre/post/verify SQL
# 依赖: psql, pg_dump (PostgreSQL 17 客户端)
#   sudo dnf install postgresql17 dos2unix
#   dos2unix generate_migration_scripts.sh && bash generate_migration_scripts.sh
set -e
 
# ==================== 配置区(按需修改)====================
SRC_HOST="10.0.1.20";  SRC_PORT="5432"; SRC_DB="appdb"; SRC_USER="postgres"; SRC_PASSWORD="<源库口令>"
TGT_HOST="mytarget.abcdefg.us-east-1.rds.amazonaws.com"; TGT_PORT="5432"; TGT_DB="appdb"; TGT_USER="postgres"; TGT_PASSWORD="<目标口令>"
OUTPUT_DIR="./migration_scripts_$(date +%Y%m%d_%H%M%S)"
EXCLUDE_TABLES="awsdms_ddl_audit"
# =========================================================
export PGPASSWORD="$SRC_PASSWORD"
mkdir -p "$OUTPUT_DIR"
 
# [0] 源库全表 REPLICA IDENTITY FULL
psql -h "$SRC_HOST" -U "$SRC_USER" -d "$SRC_DB" -t -A -c "
  SELECT 'ALTER TABLE '||table_schema||'.'||table_name||' REPLICA IDENTITY FULL;'
  FROM information_schema.tables
  WHERE table_schema NOT IN ('pg_catalog','information_schema') AND table_type='BASE TABLE';
" >> "$OUTPUT_DIR/00_set_source_db_identity_full.sql"
 
# [1] pre-data(表结构/序列/默认值/函数)
pg_dump -h "$SRC_HOST" -U "$SRC_USER" -d "$SRC_DB" --schema-only --section=pre-data \
  --no-owner --no-privileges --no-tablespaces --exclude-table="$EXCLUDE_TABLES" \
  -f "$OUTPUT_DIR/01_pre_data.sql"
 
# [2] 禁用触发器 + session_replication_role=replica
psql -h "$SRC_HOST" -U "$SRC_USER" -d "$SRC_DB" -t -A -c "
  SELECT DISTINCT 'ALTER TABLE '||event_object_schema||'.'||event_object_table||' DISABLE TRIGGER USER;'
  FROM information_schema.triggers
  WHERE trigger_schema NOT IN ('pg_catalog','information_schema')
    AND trigger_name NOT LIKE 'RI_ConstraintTrigger_%';
" >> "$OUTPUT_DIR/02_pre_dms_disable_triggers.sql"
echo "ALTER ROLE $TGT_USER SET session_replication_role='replica';" >> "$OUTPUT_DIR/02_pre_dms_disable_triggers.sql"
 
# [3] post-data(索引/外键/CHECK/UNIQUE/触发器)
pg_dump -h "$SRC_HOST" -U "$SRC_USER" -d "$SRC_DB" --schema-only --section=post-data \
  --no-owner --no-privileges --no-tablespaces --exclude-table="$EXCLUDE_TABLES" \
  -f "$OUTPUT_DIR/03_post_data.sql"
 
# [4] 序列重置 + 启用触发器 + ANALYZE  → 04_post_dms_restore.sql
# [5] 一致性校验 SQL                    → 05_verify.sql
# [6] Amazon DMS 任务配置参考 + RUN_ORDER.md(执行清单)
echo "✅ 生成完成,按 RUN_ORDER.md 执行"

执行上述脚本后生成 RUN_ORDER.md ,其执行顺序为:Step 0 源库 IDENTITY FULL → Step 1~3 目标库预建结构/禁触发器/建 Amazon DMS 辅助表 → Step 4 Amazon DMS 同构迁移“转换或迁移至托管”任务(全量+增量)→ Step 5~6 补齐索引约束触发器/重置序列 → Step 7 校验并切换。

十一、总结

同构 PostgreSQL 迁移中,若源库结构标准符合 Amazon DMS 的功能前置条件,Amazon DMS 的“转换或迁移至托管”可直接参照官方文档操作完成;但当源库含触发器、或有无主键的 LOB 表等情况时,直接“开箱即用”会遇到问题,需要其他方案或脚本配合。配合脚本辅助完成预建结构、禁用/恢复触发器、并补齐次级对象等操作——本项目即以此方式用同构迁移顺利完成。相同的脚本思路与关键配置在“迁移和复制”方式下亦验证通过,可作为参考。

本文将真实迁移项目中沉淀的可复用的脚本生成器 + 一份可照做的 RUN_ORDER 执行清单进行分享和说明,并用项目实践验证了“缺失对象”的普遍性与补齐顺序。该方案与业务表无关、可随 Schema 变更重复再生,可作为任何同构 PostgreSQL 上云项目的参考模板,帮助读者少踩坑、快落地。

最后,读者可以基于本文的脚本与执行清单,快速在自己的同构 PostgreSQL 迁移中落地:只需修改脚本顶部的连接配置并按 RUN_ORDER 执行,即可复用本文验证过的迁移与校验流程,并在此基础上进一步适配自身的 schema 与业务需求。

➡️ 下一步行动:

相关产品:

相关文章:

十二、相关链接

*前述特定亚马逊云科技生成式人工智能相关的服务目前在亚马逊云科技海外区域可用。亚马逊云科技中国区域相关云服务由西云数据和光环新网运营,具体信息以中国区域官网为准。

本篇作者

黄振武

西云数据解决方案架构师,曾就职于多家外企、头部央企,专注于云计算和 AI 解决方案设计和技术咨询,20+ 年软件开发、项目交付、咨询等丰富的行业实践经验,擅长系统架构、容器/云原生、AI 等领域。


AWS 架构师中心:云端创新的引领者

探索 AWS 架构师中心,获取经实战验证的最佳实践与架构指南,助您高效构建安全、可靠的云上应用