本文档提供了详细的说明,介绍如何使用 实时迁移 策略将数据从您的 PostgreSQL 数据库迁移到 Timescale 实例,同时最大限度地减少生产应用程序的停机时间(大约几分钟)。为了简化迁移,我们为您提供了一个 Docker 镜像,其中包含执行实时迁移所需的所有工具和脚本。

您应该预配一个专用实例来运行迁移步骤。此实例应该有足够的空间来容纳在复制数据时发生的缓冲更改。这与在此期间写入数据库的新数据量(未压缩)大致成正比。一般来说,介于 100 GB 和 500 GB 之间应该就足够了。

注意

在迁移的上下文中,您现有的生产数据库被称为“源”数据库,而您打算将数据迁移到的新 Timescale 数据库被称为“目标”数据库。

详细来说,迁移过程包括以下步骤

  1. 在 Timescale 中设置目标数据库实例。
  2. 准备源数据库以进行实时迁移。
  3. 运行实时迁移 Docker 镜像。
  4. 验证目标数据库中的数据,并将其用作新的主数据库。
提示

如果您遇到困难,可以通过打开支持请求或将您的问题提交到 社区 Slack 中的 #migration 频道寻求帮助,此迁移方法的开发人员将在那里为您提供帮助。

您可以直接从 Timescale 控制台 或通过电子邮件发送至 support@timescale.com 打开支持请求。

在 Timescale 中创建数据库服务.

如果您打算迁移超过 400 GB 的数据,请打开支持请求以确保您的 Timescale 实例上预先分配了足够的磁盘空间。

您可以直接从 Timescale 控制台 或通过电子邮件发送至 support@timescale.com 打开支持请求。

注意

为了方便起见,本指南中将源数据库和目标数据库的连接字符串分别称为 $SOURCE$TARGET。这可以在您的 shell 中设置,例如

export SOURCE=postgres://<user>:<password>@<source host>:<source port>/<db_name>
export TARGET=postgres://<user>:<password>@<target host>:<target port>/<db_name>
重要

不要使用 Timescale 连接池连接进行实时迁移。使用连接池可能会出现许多问题,而且没有任何优势。非常小的实例可能默认情况下没有配置足够的连接,在这种情况下,您应该修改实例中的 max_connections 值,如 配置数据库参数 中所示。

确保源数据库中的 old_snapshot_threshold 值设置为默认值 -1 非常重要。这可以防止 PostgreSQL 将快照中的数据视为已过时。如果此值设置为除 -1 之外的值,则可能会影响现有数据迁移步骤。

要检查 old_snapshot_threshold 的当前值,请运行以下命令

psql -X -d $SOURCE -c 'show old_snapshot_threshold'

如果查询返回的值不是 -1,则必须更改它。

如果您在自托管数据库上拥有超级用户,请运行以下命令

psql -X -d $SOURCE -c 'alter system set old_snapshot_threshold=-1'

否则,如果您使用的是托管服务,请使用您的云提供商的配置机制将 old_snapshot_threshold 设置为 -1

接下来,您应该将 wal_level 设置为 logical,以便预写日志 (WAL) 记录逻辑解码所需的 information。

要检查 wal_level 的当前值,请运行以下命令

psql -X -d $SOURCE -c 'show wal_level'

如果查询返回的值不是 logical,则必须更改它。

如果您在自托管数据库上拥有超级用户,请运行以下命令

psql -X -d $SOURCE -c 'alter system set wal_level=logical'

否则,如果您使用的是托管服务,请使用您的云提供商的配置机制将 wal_level 设置为 logical

重新启动您的数据库以使更改生效,并验证设置是否反映在您的数据库中。

接下来,您需要确保源表和超表已设置主键或 REPLICA IDENTITY。这很重要,因为它是复制 DELETEUPDATE 操作的必要条件。副本标识帮助复制过程识别正在修改的行。它默认使用表的 primary key。

如果表没有主键,则必须手动设置副本标识。一种选择是使用仅包含标记为 NOT NULL 的列的唯一、非部分、非延迟索引。这可以设置为副本标识

ALTER TABLE {table_name} REPLICA IDENTITY USING INDEX {_index_name}

如果没有主键或可用的唯一索引可用,则必须将 REPLICA IDENTITY 设置为 FULL。如果您预计在表上进行大量的 UPDATEDELETE 操作,则不建议使用 FULL。对于每个 UPDATEDELETE 语句,PostgreSQL 都要读取整个表以查找所有匹配的行,这会导致复制速度明显变慢。

ALTER TABLE {table_name} REPLICA IDENTITY FULL

接下来,下载实时迁移 Docker 镜像

docker run --rm -it --name live-migration \
-e PGCOPYDB_SOURCE_PGURI=$SOURCE \
-e PGCOPYDB_TARGET_PGURI=$TARGET \
--pid=host \
-v ~/live-migration:/opt/timescale/ts_cdc \
timescale/live-migration:v0.0.23 --help
Live migration moves your PostgreSQL/TimescaleDB to Timescale Cloud with minimal downtime.
options:
-h, --help Show this help message and exit
-v, --version Show the version of live-migration tool
Subcommands:
{snapshot,clean,migrate}
Subcommand help
snapshot Create a snapshot
clean Clean up resources
migrate Start the migration

实时迁移包含 3 个子命令

  1. 快照
  2. 清理
  3. 迁移

从高层次来看,

snapshot 子命令会创建到源数据库的 Postgres 快照连接以及复制槽。这是运行 migrate 子命令的先决条件。

migrate 子命令通过利用 snapshot 子命令创建的快照和复制槽来执行实时迁移过程。

clean 子命令旨在删除与实时迁移相关的资源。它应该在迁移成功完成后运行,或者如果您需要从头开始重新启动迁移过程,则应运行它。如果您想恢复上一次中断的实时迁移,则不应运行 clean

执行此命令以建立快照连接;不要中断该过程。为了方便起见,请考虑使用终端多路复用器(如 tmuxscreen),这使命令可以在后台运行。

docker run --rm -it --name live-migration-snapshot \
-e PGCOPYDB_SOURCE_PGURI=$SOURCE \
-e PGCOPYDB_TARGET_PGURI=$TARGET \
--pid=host \
-v ~/live-migration:/opt/timescale/ts_cdc \
timescale/live-migration:v0.0.23 snapshot

除了创建快照之外,此过程还会验证源和目标上的先决条件,以确保数据库实例已准备好进行复制。

例如,它会检查源上的所有表是否都已设置了主键或 REPLICA IDENTITY。如果没有,它会显示一条警告消息,列出没有 REPLICA IDENTITY 的表,并在继续创建快照之前等待用户确认。

2024-03-25T12:40:40.884 WARNING: The following tables in the Source DB have neither a primary key nor a REPLICA IDENTITY (FULL/INDEX)
2024-03-25T12:40:40.884 WARNING: UPDATE and DELETE statements on these tables will not be replicated to the Target DB
2024-03-25T12:40:40.884 WARNING: - public.metrics
Press 'c' and ENTER to continue

migrate 子命令支持以下标志

docker run --rm -it --name live-migration-migrate \
-e PGCOPYDB_SOURCE_PGURI=$SOURCE \
-e PGCOPYDB_TARGET_PGURI=$TARGET \
--pid=host \
-v ~/live-migration:/opt/timescale/ts_cdc \
timescale/live-migration:v0.0.23 migrate --help
usage: main.py migrate [-h] [--dir DIR] [--resume] [--skip-roles] [--table-jobs TABLE_JOBS] [--index-jobs INDEX_JOBS]
[--skip-extensions [SKIP_EXTENSIONS ...]] [--skip-table-data SKIP_TABLE_DATA [SKIP_TABLE_DATA ...]]
options:
-h, --help Show this help message and exit
--resume Resume the migration
--skip-roles Skip roles migration
--table-jobs TABLE_JOBS
Number of parallel jobs to copy "existing data" from source db to target db (Default: 8)
--index-jobs INDEX_JOBS
Number of parallel jobs to create indexes in target db (Default: 8)
--skip-extensions [SKIP_EXTENSIONS ...]
Skips the given extensions during migration. Empty list skips all extensions.
--skip-table-data SKIP_TABLE_DATA [SKIP_TABLE_DATA ...]
Skips data from the given table during migration. However, the table schema will be migrated. To skip data from a
Hypertable, you will need to specify a list of schema qualified chunks belonging to the Hypertable. Currently, this
flag does not skip data during live replay from the specified table. Values for this flag must be schema qualified. Eg:
--skip-table-data public.exclude_table_1 public.exclude_table_2

接下来,我们将启动迁移过程。打开一个新的终端,并启动实时迁移,并允许它持续运行。

docker run --rm -it --name live-migration-migrate \
-e PGCOPYDB_SOURCE_PGURI=$SOURCE \
-e PGCOPYDB_TARGET_PGURI=$TARGET \
--pid=host \
-v ~/live-migration:/opt/timescale/ts_cdc \
timescale/live-migration:v0.0.23 migrate
注意

如果 migrate 命令在执行过程中因任何原因停止,则可以通过添加 --resume 标志从停止的地方恢复迁移。这只有在 snapshot 命令完好无损且使用卷挂载(如 ~/live-migration)时才有可能。

migrate 将利用上一步中创建的快照并将模式迁移到目标数据库。迁移模式后,它会提示您在目标数据库中创建超表。

理想情况下,包含时间序列数据的表应该转换为超表。您需要为要转换为目标数据库中超表的每个表运行 create_hypertable()。有关详细信息,请参见 超表文档

创建完超表后,您需要发出“继续”信号才能继续。您可以按 c 键来执行此操作。

接下来,实时迁移会将源数据库中的现有数据迁移到目标数据库。然后,它会将源端接收到的实时事务(实时回放)流式传输到目标端。在此过程中,它将显示回放过程的状态。

Live-replay will complete in 1 minute 38.631 seconds (source_wal_rate: 106.0B/s, target_replay_rate: 589.0KiB/s, replay_lag: 56MiB)

如果实时回放无法跟上源数据库的负载,您会看到类似以下的 message

WARN live-replay not keeping up with source load (source_wal_rate: 3.0MiB/s, target_replay_rate: 462.0KiB/s, replay_lag: 73MiB)

实时回放追上后,实时迁移会显示以下信息

Target has caught up with source (source_wal_rate: 751.0B/s, target_replay_rate: 0B/s, replay_lag: 7KiB)
To stop replication, hit 'c' and then ENTER
重要

应用程序停机时间从这里开始。请确保您有策略在将应用程序脱机之前验证目标数据库中的数据,以最大限度地减少整体停机时间。

实时回放追上后,并且您已准备好将应用程序脱机,请停止所有写入源数据库的应用程序。这标志着停机阶段的开始,此阶段将持续到您 验证 了目标数据库中的数据。

停止写入源数据库允许实时迁移过程完成将数据复制到目标数据库。

当您看到 目标已追上源 消息,并且您的应用程序没有写入数据库时,请按 c 键,然后按 ENTER 键停止复制。

Target has caught up with source (source_wal_rate: 46.0B/s, target_replay_rate: 0B/s, replay_lag: 221KiB)
To stop replication, hit 'c' and then ENTER

实时迁移工具会继续剩余的工作,包括迁移序列和清理资源。迁移完成后,您会看到以下 message

Migration successfully completed

现在,所有数据都已迁移,两个数据库的内容应该相同。如何最好地验证这一点取决于您的应用程序。您可以比较行数或列的聚合以验证目标数据库是否与源数据库匹配。

重要

应用程序停机时间从这里结束。

当您对数据验证感到满意后,最后一步是配置您的应用程序以使用目标数据库。

要清理与实时迁移相关的资源,请使用以下命令

docker run --rm -it --name live-migration-clean \
-e PGCOPYDB_SOURCE_PGURI=$SOURCE \
-e PGCOPYDB_TARGET_PGURI=$TARGET \
--pid=host \
-v ~/live-migration:/opt/timescale/ts_cdc \
timescale/live-migration:v0.0.23 clean --prune

--prune 标志用于删除 ~/live-migration 目录中用于迁移过程的临时文件。请注意,执行 clean 命令意味着您无法恢复中断的实时迁移。

关键字

在这页上发现问题了吗?报告问题 或 在 GitHub 上编辑此页面