零停机时间 PostgreSQL 迁移
零停机时间 PostgreSQL 迁移对于在更改数据库模式或执行其他维护任务时保持应用程序的可用性和可靠性至关重要。
遵循这些简单的规则,避免常见的陷阱,并在没有计划外停机的情况下将更改应用于您的数据库。
使用事务
将您的迁移脚本包含在事务块中。如果迁移的任何部分失败,整个事务将回滚,确保您的数据库保持其先前状态。
避免长时间运行的事务
在事务中运行迁移意味着在事务结束之前,事务中所做的更改是不可见的。这正是我们在应用迁移时需要的,但在实践中效果不佳。
使用事务会导致 PostgreSQL 在事务持续期间维护数据库的两个版本。一个带有您的更改,另一个没有。PostgreSQL 事务 非常适合此类任务,但它们也有其局限性。
PostgreSQL 还必须持有迁移期间获得的所有锁。例如,更新一行会锁定该行,因此您的更改不会被另一个事务覆盖。PostgreSQL 仅在事务结束时释放锁。如果并发事务实际上更改了同一行,则迁移将失败。
仅当您的迁移很小且很快(少于 5-10 秒)时,使用事务才有效。即使对于中等数据库,使用长时间运行的事务也会使迁移变慢(在某些情况下慢 10 倍)或导致迁移失败。
将长时间运行的查询拆分为较小的批次
PostgreSQL 在事务中运行每个查询。因此,不使用 BEGIN
和 COMMIT
并不意味着您没有使用事务。这意味着您需要将长时间运行的查询拆分为更小的查询,并避免大型事务,原因如上所述。
例如,您需要更新 100 万行。不要使用单个 UPDATE
查询来执行此操作。而是将作业拆分为 10 个批次,每个批次包含 10 万行。并分别对每个批次执行相同的 UPDATE
查询。现在您有 10 个查询而不是 1 个,但您可以确保迁移会成功。
以一致的顺序更新行
如果可能,请以一致的顺序更新行。这有助于避免在两个并发事务尝试以不同顺序更新同一行时出现死锁。
例如,当事务 1 锁定行 #1 并且事务 2 锁定行 #2 时,就会发生死锁。现在事务 1 等待行 #2 的锁,而事务 2 等待行 #1 的锁。它们互相锁定,PostgreSQL 必须杀死其中一个。
不好
-- transaction 1
UPDATE test WHERE id IN (1, 2);
-- transaction 2
UPDATE test WHERE id IN (2, 1);
好
-- transaction 1
UPDATE test WHERE id IN (1, 2);
-- transaction 2
UPDATE test WHERE id IN (1, 2);
当您使用 INSERT ON CONFLICT DO UPDATE
时,相同的规则适用。在这种情况下,您可能需要在插入之前对行进行排序。
不要添加带有 NOT NULL 的列
像 ADD column NOT NULL
这样的查询在已经有一些行的表上会失败。因为现有行没有新添加列的值,所以 PostgreSQL 拒绝添加该列。
> ALTER TABLE test ADD COLUMN foo text NOT NULL;
ERROR: column "foo" of relation "test" contains null values
您的替代方案是
- 添加一个默认值,例如,
foo text NOT NULL DEFAULT ''
。 - 完全删除
NOT NULL
并添加一些针对NULL
的验证。 - 将查询拆分为多个迁移
-- migration 1
ALTER TABLE test ADD COLUMN foo text;
-- migration 2
UPDATE test SET foo = '';
-- migration 3
ALTER TABLE test ALTER COLUMN foo SET NOT NULL;
创建临时表
在某些情况下,您可以使用新模式创建临时表,从旧表复制数据,然后原子地交换表。这最大限度地减少了迁移期间的停机时间。
滚动部署
为您的应用程序实施滚动部署。这涉及逐步部署新代码并迁移数据库,一次一个实例或节点,同时保持其他实例或节点运行。
监控 PostgreSQL
要 监控 PostgreSQL,您可以使用 OpenTelemetry PostgreSQL 接收器,它随 OpenTelemetry 收集器一起提供。
OpenTelemetry 收集器 是一个代理,它从您要监控的系统中提取遥测数据,并使用 OpenTelemetry 协议 (OTLP) 将其发送到 OpenTelemetry 后端。
Uptrace 是一个 DataDog 竞争对手,支持分布式跟踪、指标和日志。您可以使用它来监控应用程序并排查问题。
Uptrace 带有一个直观的查询构建器、丰富的仪表板、带有通知的警报规则以及大多数语言和框架的集成。
Uptrace 可以在一台服务器上处理数十亿个跨度和指标,并允许您以 10 倍更低的成本监控您的应用程序。
只需几分钟,您就可以通过访问 云演示(无需登录)或使用 Docker 在本地运行它。源代码可在 GitHub 上获得。
结论
零停机时间 PostgreSQL 迁移需要仔细的计划、测试和协调。至关重要的是,要平衡进行模式更改的需要与保持高可用性和高性能应用程序的目标。