本文档提供详细的说明,使用 实时迁移 策略,将数据从您的 TimescaleDB 数据库(自托管或在 TimescaleDB 托管服务 上)迁移到 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) 记录逻辑解码所需的信息。

要检查 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
重要

TimescaleDB 2.12 及更高版本允许在超表上设置 REPLICA IDENTITY。但是,如果您使用的是低于 2.12 的版本,则您的超表必须具有主键。如果没有,您需要升级您的 TimescaleDB 实例。这是因为,如果没有主键或 REPLICA IDENTITYDELETEUPDATE 等操作将不会被复制,这会影响迁移后数据的一致性。

接下来,下载实时迁移 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

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

例如,它会检查源上所有表是否都具有 PRIMARY KEY 或 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
注意

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

migrate 命令使用在先前步骤中创建的快照,并将现有数据迁移到目标。然后,它会将事务从源流式传输到目标。在此过程中,您会看到回放过程状态

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)

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

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

实时迁移工具会继续完成剩余的工作,包括复制 TimescaleDB 元数据、序列和运行策略。迁移完成后,您会看到以下消息

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上编辑此页面