PostgreSQL版本之间的逻辑复制


有多种更新PostgreSQL的方法,但是有些方法会导致停机。 如果要避免停机,请根据情况使用复制进行升级-逻辑或物理(流式)。 在本文中,我们将探讨PostgreSQL中逻辑复制和物理复制之间的区别。 然后,我们将详细讨论如何使用逻辑复制来更新版本,同时避免应用程序停机。 下一篇文章将讨论物理复制。


在先前的文章中,我们已经讨论了升级PostgreSQL的方法( 使用pg_dumpall 升级PostgreSQL使用pg_dump / pg_restore升级PostgreSQL )作为升级或迁移旧PostgreSQL版本系列的一部分。 但是这两种方法都不能排除停机时间。


逻辑复制类型


在这里,我们讨论两种复制类型:


  • 使用内置逻辑复制在PostgreSQL 10和11之间进行复制。
  • 使用pgologic扩展在PostgreSQL 9.4(或PG 11之前)和PostgreSQL 11之间进行复制

为了最大程度地减少停机时间,您可以使用复制进行升级。 当所有相关数据都复制到另一台最新的PostgreSQL服务器上时,您只需将应用程序转移到新服务器上,停机时间最少,尽管当然,这全都取决于应用程序堆栈的复杂性。


PostgreSQL中的逻辑复制允许用户有选择地复制表并打开备份服务器以进行写操作。 PostgreSQL中的物理复制是按块完成的。 在这种情况下,向导中的每个数据库都将复制到备份服务器,无法进行写操作。 接下来,我们将称为物理复制


在备用服务器上使用逻辑复制时,可以启用来自多个主服务器的复制。 在需要将数据从多个PostgreSQL(OLTP)数据库复制到单个PostgreSQL服务器以进行报告和数据存储的情况下,这很有用。


逻辑复制优于流传输的主要优点是,使用逻辑复制,您可以将更改从旧版本的PostgreSQL复制到新版本。 仅当主服务器和备用服务器具有相同的主版本时,流复制才起作用。 理想情况下,其他版本也应匹配。


在PostgreSQL 10和11之间复制


从PostgreSQL 10开始,默认情况下可以使用逻辑复制。 因此,您可以轻松地在PostgreSQL 11中复制PostgreSQL 10数据库。逻辑复制使用发布和订阅模型。 提交更改的节点将成为发布者。 订阅这些更改的节点将成为订户。 每个出版物可以有多个订阅。


过帐


发布是由一组表创建的一组更改。 它称为变更 复制集 。 发布只能包含表,而不能包含其他对象。 这些表中的DML可以复制,但DDL无法复制。


在出版物中,您可以选择要复制的DML类型:INSERT,DELETE,UPDATE或ALL。 默认情况下,选择全部。 该表必须具有一个副本标识符,以便将UPDATE和DELETE操作复制到订阅服务器。 副本标识符可帮助您查找已更新或删除的行。


该表的主键是默认副本标识符。 或者,您可以使标识符成为具有NOT NULL值的唯一索引。 如果您没有主键或唯一索引(没有NO NULL值),请将copy_identity设置为FULL。 在这种情况下,Postgres使用整个字符串作为键。 但这不是很合理。


如果在执行UPDATE或DELETE操作后默认情况下没有主键和副本标识符的表添加到发布,则可能会发生错误。


订阅方式


订户可以订阅一个或多个出版物。 在添加订阅之前,请确保已在订阅者节点上创建复制的表。 为此,仅将方案从发布者转储到订阅者。


逻辑复制示例


以下示例仅在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; 

在PostgreSQL 9.4和PostgreSQL 11之间复制


PostgreSQL 10之前的版本该怎么办? 对于版本9.4到11,有一个特殊的扩展名pglogical 。 使用pgologic,您可以通过两种方式将PostgreSQL 9.4复制到PostgreSQL 11。


以下是使用pgologic扩展名在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:] $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.然后通过向几个表发送请求来检查复制状态,pgologic总是更新:


 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) 

主键选择


在第二步中,您看到了如何通过为没有一个表的主键创建主键的方式将所有表添加到复制集中。 我可能为此表选择了错误的主键,但这仅用于演示。 选择主键时,请确保它是正确的。 它必须是唯一的,并且使用不包含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. 

这是使用pgologic在旧版本和新版本PostgreSQL之间创建复制的方法。 设置复制后,只需将应用程序切换到最新版本,以使停机时间最少。

Source: https://habr.com/ru/post/zh-CN457512/


All Articles