无需停机即可在生产服务器上更新 Postgres

无需停机即可在生产服务器上更新 Postgres

我有一台运行 Postgres 9.4 的生产服务器。数据库大于 10 GB。是否可以在不停机和不丢失数据的情况下升级到 Postgres 9.5?

升级教程建议在执行时停止 Postgres sudo pg_upgradecluster 9.4 main,但这可能需要很长时间。更新 10 GB 集群可能需要几个小时!

我也尝试过pg_dump mydb > db.sql。在 PG 9.4 () 中删除数据库并再次插入转储psql -d mydb -f db.sql大约需要 50 分钟。

但是在 PG 9.5 中插入转储需要 7 个多小时才能完成。特别是创建索引真的很慢...

2016-07-18 00:13:55 CEST [60358-5] ERROR:  canceling autovacuum task
2016-07-18 00:13:55 CEST [60358-6] CONTEXT:  automatic analyze of table ...
2016-07-18 00:36:20 CEST [60366-1] ERROR:  canceling autovacuum task
2016-07-18 00:36:20 CEST [60366-2] CONTEXT:  automatic analyze of table ...
2016-07-18 04:21:40 CEST [60361-1] ERROR:  canceling autovacuum task
2016-07-18 04:21:40 CEST [60361-2] CONTEXT:  automatic analyze of table ...
2016-07-18 07:55:19 CEST [61316-1] ERROR:  canceling autovacuum task
2016-07-18 07:55:19 CEST [61316-2] CONTEXT:  automatic analyze of table ...

因此,这两种方法都不pg_upgradeclusterpg_dump可接受的解决方案。即使使用 PG 4,您也至少会有 50 分钟的停机时间。因此:如何在生产服务器或大型主从集群上升级数据库而不会造成停机和数据丢失?

答案1

如果没有一些集群魔法,根本不可能出现停机。

其他一些可能性:

  1. pg_upgrade与选项一起使用--link。使用此选项,不会复制原始数据库文件,而是将其硬链接到新目录,从而大大加快了该过程。请注意,此将永久改变源数据库文件。
  2. 使用pg_dump并在新数据库上恢复。您可以大大缩短暂时地在新数据库中禁用同步写入(fsync = false在新 PG 实例的配置文件中)
  3. 安装一个新的 PG 实例并让它在不同端口上运行。然后,使用pg_dump通过网络将转储加载到新实例。完成后,交换端口并使用新实例。

答案2

我想你已经解决了这个问题,所以其他遇到类似问题的人也许也可以解决。

在使用 postgresql 多年(从 8.4 版到最新 9.6 版)后,我建议在这种情况下不要“升级”。如果可以的话,请使用您使用的最新版本的操作系统(非常重要 - 可以防止许多问题)和最新的 pg 版本以及重复数据创建新的机器或新的云实例。

如何复制数据取决于您的应用程序、PostgreSQL 版本和周围环境。数据库 ~10 GB 不是很大,所以对您来说还不错。我使用的数据库 >400 GB,所以想象一下这里的问题有多复杂...

  • Pg_dump 9.4 已经允许您使用多个 CPU 核心转储到具有多个作业的目录格式,这可以大大降低转储时间 - 除非您将所有内容都放在一个大表中 :-)
  • 或者对于 pg 9.4+,您可以使用前面提到的 pglogical 扩展,这是一个非常棒的解决方案,但请注意 - 要使 pglogical 在主服务器上运行,您必须重新启动 postgres,因为必须将扩展添加到 postgresql.conf 文件中的 shared_preload_libraries='pglogical' - 请参见此处:http://postgresql.freeideas.cz/pglogical-postgresql-9-6-small-hints-debian/因此,我强烈建议先在具有相同版本的其他实例上进行测试!并且要切换到新实例,请安排一些短暂的维护窗口以将客户端切换到新数据库 - 如果连接字符串未硬编码到应用程序中 :-) - 但在这种情况下,您可以在旧机器上准备 pgbouncer,并将连接配置为新机器,停止旧数据库,将 pg 端口(假设为 5432)切换到 pgbouncer,并在可能的情况下稍后处理连接字符串...
  • 或者也许您的应用程序没有那么多新数据,您可以在两台机器上使用最新的备份和分叉插入/更新?当您确定一切正常时切换客户端?

我在现实生活中见过所有这些场景的变体。所以玩得开心!我祈祷 :-)

答案3

几乎无需停机即可升级逻辑. 至少对于 PostgreSQL >= 9.4 及更新版本它应该可以工作。

这是一个相对较新的项目(2016),其基于以下代码:PostgreSQL 的双向复制. 安装时你需要2ndQuadrant 存储库

描述用法在自述文件中,需要重新启动数据库(您必须更新复制配置)但至少它不应该导致几个小时的停机时间。

不同于替换管理器pglogical用于一次性 DB 复制,这比复制二进制 WAL 文件花费的时间要长得多。

首先为每个需要复制(升级)的数据库启用扩展:

CREATE EXTENSION pglogical;

目前所有命令都需要以超级用户身份执行(postgres)。首先创建一个“主节点”(provider):

SELECT pglogical.create_node(
    node_name := 'provider1',
    dsn := 'host=providerhost port=5432 dbname=db'
);

并标记要复制的架构:

SELECT pglogical.replication_set_add_all_tables('default', ARRAY['public']);

和序列复制:

SELECT pglogical.replication_set_add_all_sequences('default', ARRAY['public']);

请注意,每个表都需要一个主键,否则复制将无法启动。与其他备份方法不同,这里的表一致性很重要。

继续“备用节点” ( subscriber)

SELECT pglogical.create_node(
    node_name := 'subscriber1',
    dsn := 'host=thishost port=5432 dbname=db'
);

最后开始复制:

SELECT pglogical.create_subscription(
    subscription_name := 'subscription1',
    provider_dsn := 'host=providerhost port=5432 dbname=db'
);

相关内容