跨PostgreSQL大版本复制怎么做? | 逻辑复制

  • 2019 年 11 月 21 日
  • 筆記

作者

Avinash Vallarapu,Fernando Laudares Camargos,Nickolay Ihalainen,Percona公司工程师,Jobin Augustine :OpenSCG工作了2年,在戴尔做了10年的数据库专家。

译者简介

崔鹏,任职于海能达通信股份有限公司哈尔滨平台中心,数据库开发高级工程师,致力于postgresql数据库在专网通信领域、公共安全领域的应用与推广,个人兴趣主要集中在:分布式数据库系统设计、高并发高可用数据库架构设计与开源数据库的源码研究。

校对者简介

Qinghui.Guo, DBA 负责公司Cloud DB的维护,痴迷于开源架构解决方案,是PG忠实粉丝,现致力于PG分享和推广。

当需要升级PostgreSQL时,可以使用多种方法。为了避免应用程序停机,不是所有升级postgres的方法都适合,如果避免停机是必须的,那么可以考虑使用复制作为升级方法,并且根据方案,可以选择使用逻辑复制或物理(流)复制来处理此任务。我们来看看PostgreSQL中逻辑和物理复制之间的区别。然后,我们将更详细地探讨如何使用逻辑复制完成升级,并通过这样做,避免应用程序停机。在后面的文章中,我们将研究物理复制。我们已经在之前的系列文章中讨论了几种可用于升级或迁移旧版PostgreSQL到新版PostgreSQL版本的方法,使用pg_dumpall进行PostgreSQL升级和使用pg_dump/pg_restore进行PostgreSQL升级。但是,这两种方法都涉及到应用程序的停机时间。

1 逻辑复制的类型

这里我们介绍两种您可以实现的复制类型:

1.使用内置逻辑复制在PostgreSQL 10和11版本之间进行复制。

2.使用pglogical的扩展在PostgreSQL 11和PostgreSQL 9.4或低于PostgreSQL11版本之间进行复制。

我们可能会选择通过复制作为升级方法,以最大限度地减少应用程序的停机时间。一旦所有数据都被复制到最新版本的另一个PostgreSQL服务器上,您只需将应用程序切换到新服务器,停机时间最短,但这当然取决于应用程序的复杂性。

PostgreSQL中的逻辑复制允许用户执行表级别的复制,并允许备库可以写入。而PostgreSQL中的物理复制是块级复制。在这种情况下,主服务器中的每个数据库都将复制到备用数据库,并且备库以只读方式打开并不可以写入,我们将物理复制称为流复制。

通过逻辑复制,备用数据库可以从多个主服务器启用复制。在需要将数据从多个PostgreSQL数据库(OLTP)复制到单个PostgreSQL服务器以进行报表和数据仓库业务的情况下,这么做会对业务有所帮助。

逻辑复制的最大优势之一是逻辑复制允许我们将旧版本的PostgreSQL的DML复制到更高版本。物理流复制只有在主数据库版本和备用数据库版本都是相同的时才有效。最佳的实施方案,是主库和备库使用相同的版本。

2 PostgreSQL 10和11版本之间的复制

从PostgreSQL 10开始,默认情况下PostgreSQL支持逻辑复制。因此,您可以轻松地将PostgreSQL 10数据库复制到PostgreSQL 11.逻辑复制使用发布和订阅模式。发送更改的节点称为发布者。订阅这些更改的节点称为订阅者。可以有一个或多个订阅者。

2.1 发布者

发布者是从一组表生成的一组更改。它被称为更改集或复制集。发布者只能包含表,不能包含任何其他对象。只支持复制这些表上的DML操作变更,但不能复制DDL操作变更。

在发布者中,可以选择要复制的DML类型:INSERT或DELETE或UPDATE或ALL。默认情况下复制全部。您必须在要发布的表上设置标识,以将UPDATES和DELETES复制到订阅者。标识有助于识别要更新或删除的行。

表的主键是其默认标识。还可以使用NO NULL值创建唯一索引作为标识。如果没有主键或具有NO NULL的唯一索引,则可以将replica_identity设置为FULL。当标识设置为FULL时,postgres将整行用作键。当然,这可能使复制效率下降。

如果在UPDATE或DELETE操作之后将没有主键和非默认标识的表添加到发布中,则可能会发生错误。

2.2 订阅者

订阅者可以订阅一个或多个发布者。在添加订阅之前,必须确保已在订阅节点中创建了要复制的表,当然你可以通过在发布节点转储模式元数据到订阅节点实现。

2.3 逻辑复制的一个示例

以下示例步骤仅适用于PostgreSQL 10和11版本之间的逻辑复制。在发布节点上,创建发布。您可以添加所有表,也可以选择将选定的表添加到发布中。

-- For adding ALL Tables in Database    CREATE PUBLICATION percpub FOR ALL TABLES;    -- For adding Selected Tables in Database    CREATE PUBLICATION percpub FOR TABLE scott.employee scott.departments;

在订阅者节点上,创建引用发布者节点上的发布的订阅。如上所述,在创建订阅之前,将表的DDL转储执行到订阅者节点,

$ pg_dump -h publisher_server_ip -p 5432 -d percona -Fc -s -U postgres | pg_restore -d percona -h subscriber_node_ip -p 5432 -U postgres    CREATE SUBSCRIPTION percsub CONNECTION 'host=publisher_server_ip dbname=percona user=postgres password=secret port=5432' PUBLICATION percpub;

上述命令还会复制表中预先存在的数据。如果要禁用预先存在的数据的副本,可以使用以下语法。然后,它将在您运行此命令后才开始将更改复制到发布者。

CREATE SUBSCRIPTION percsub CONNECTION 'host=publisher_server_ip dbname=percona user=postgres password=oracle port=5432' PUBLICATION percpub WITH (copy_data = false);

在发布节点上使用以下命令监视复制。

$ psql  x  select * from pg_stat_replication;

3 PostgreSQL 9.4和PostgreSQL 11之间的复制

现在,那些比PostgreSQL 10更旧的版本呢?为此,有一个名为pglogical的扩展 ,适用于从9.4到11的版本。使用pglogical,您可以轻松地将PostgreSQL 9.4复制到PostgreSQL 11。

以下步骤演示了使用pglogical扩展在PG 9.4和PG 11之间设置复制的过程。

步骤1:将 pgserver_94视为具有数据库的源服务器:在PostgreSQL 9.4上运行的percona_94。创建以下扩展名。

[pgserver_94:] $psql -d percona_94 -c "CREATE EXTENSION pglogical_origin"  CREATE EXTENSION  [pgserver_94:] $psql -d percona_94 -c "CREATE EXTENSION pglogical"  CREATE EXTENSION

步骤2:现在,您可以继续添加选定的表或模式中的所有表或多个模式以进行复制。在以下示例中,当其中一个表上没有主键时,可以看到错误。

[pgserver_94:] $psql -d percona_94  psql (9.4.21)  Type "help" for help.  percona_94=# SELECT pglogical.create_node(node_name := 'provider1',dsn := 'host=192.168.0.24 port=5432 dbname=percona_94');  create_node  -------------  2976894835  (1 row)  percona_94=# SELECT pglogical.replication_set_add_all_tables('default', ARRAY['public']);  ERROR: table pgbench_history cannot be added to replication set default  DETAIL: table does not have PRIMARY KEY and given replication set is configured to replicate UPDATEs and/or DELETEs  HINT: Add a PRIMARY KEY to the table  percona_94=# ALTER TABLE pgbench_history ADD PRIMARY KEY (tid,aid,delta);  ALTER TABLE  percona_94=# SELECT pglogical.replication_set_add_all_tables('default', ARRAY['public']);  replication_set_add_all_tables  --------------------------------  t  (1 row)

步骤3:在订阅者节点(即PostgreSQL 11数据库)上,您可以运行类似的命令,如下所示。

创建

pgserver_11,创建以下扩展名。

[pgserver_11:] $psql -d percona_94 -c "CREATE EXTENSION pglogical_origin"  CREATE EXTENSION  [pgserver_11:] $psql -d percona_94 -c "CREATE EXTENSION pglogical"  CREATE EXTENSION    [pgserver_11:] $psql -d percona_11  psql (11.2)  Type "help" for help.  percona_11=# SELECT pglogical.create_node(node_name := 'subscriber1',dsn := 'host=127.0.0.1 port=5432 dbname=percona_11 password=secret');   create_node  -------------     330520249  (1 row)  percona_11=# SELECT pglogical.create_subscription(subscription_name := 'subscription1',provider_dsn := 'host=192.168.0.24 port=5432 dbname=percona_94 password=secret');   create_subscription  ---------------------            1763399739  (1 row)  

步骤4:然后,您可以通过查询pglogical始终更新的几个表来验证复制状态:

percona_11=# select * from pglogical.local_sync_status;   sync_kind | sync_subid | sync_nspname |   sync_relname   | sync_status | sync_statuslsn  -----------+------------+--------------+------------------+-------------+----------------   f         | 1763399739 | public       | pgbench_accounts | r           | 0/2EB7D48   f         | 1763399739 | public       | pgbench_history  | r           | 0/2EB7D48   f         | 1763399739 | public       | pgbench_tellers  | r           | 0/2EB7D48   f         | 1763399739 | public       | pgbench_branches | r           | 0/2EB7D48   d         | 1763399739 |              |                  | r           | 0/0  (5 rows)  percona_11=# select * from pglogical.subscription;     sub_id   |   sub_name    | sub_origin | sub_target | sub_origin_if | sub_target_if | sub_enabled |             sub_slot_name              |         sub_rep  lication_sets          | sub_forward_origins | sub_apply_delay  ------------+---------------+------------+------------+---------------+---------------+-------------+----------------------------------------+----------------  -----------------------+---------------------+-----------------   1763399739 | subscription1 | 2976894835 |  330520249 |    2402836775 |    2049915666 | t           | pgl_percona_11_provider1_subscription1 | {default,defaul  t_insert_only,ddl_sql} | {all}               | 00:00:00  (1 row)

3.1 主键选择

在第2步中,您了解了模式的所有表:public没有主键的表通过创建主键,从而添加到复制集。我选择的主键可能不符合业务逻辑,因为它仅用于演示。但是,当您选择主键时,请确保选择符合程序逻辑的键。它必须始终是唯一的,并使用通常不包含NULL的列。如果不彻底研究主键选择,可能会导致应用程序停机。以下是您可能遇到的示例错误:

[pgserver_94:] $pgbench -c 10 -T 300 -n percona_94  Client 7 aborted in state 12: ERROR: duplicate key value violates unique constraint "pgbench_history_pkey"  DETAIL: Key (tid, aid, delta)=(7, 63268, 2491) already exists.

到目前为止,我们已经看到了如何使用pglogical在较旧版本和较新版本PostgreSQL之间创建复制。设置复制后,您可以轻松地将应用程序切换到最新版本,同时降低停机时间。

翻译者 崔鹏

原文出处

请点击“文章底部”阅读原文进行查看。

https://www.percona.com/blog/2019/04/04/replication-between-postgresql-versions-using-logical-replication/