PG Logical Replication 邏輯複製

  • 2019 年 10 月 4 日
  • 筆記

PG10 到 PG11 的邏輯複製

我下面演示的PG環境是單機多實例的方式部署在同一台物理機上的。部署方式可以參考 上一篇博客。

1、當前老的PG10主庫(需要先設置wal_level = logical):

su - postgres   cd /usr/local/pgsql-10.10/    ./bin/psql --port 5433    postgres=# create database testdb1;  CREATE DATABASE  postgres=# create database testdb2;  CREATE DATABASE    postgres=# c testdb1  You are now connected to database "testdb1" as user "postgres".  testdb1=# create table tb1(a int ,b int, c int );  testdb1=# create table tb2(a int ,b int, c int );  testdb1=# create table tb3(a int ,b int, c int );

創建一個複製用的賬號

CREATE USER repuser REPLICATION LOGIN CONNECTION LIMIT 10 ENCRYPTED PASSWORD 'repuser';    另外,還需要給 repuser 用戶對源庫、源表、源schmea 賦權  c testdb1  grant connect on database testdb1 to repuser;  grant usage on schema public to repuser;  grant select on all tables in schema public to repuser;  -- 這個授權有點大,但是問題不算太嚴重

然後,還要去pg_hba.conf 放開 repuser賬號的訪問地址,如下:

host    all     repuser    192.168.2.1/24      md5

然後,reload下pg的配置。

2、初始化PG11新庫

cd /usr/local/pgsql-11.5  mkdir data    ./bin/initdb -D data    ./bin/pg_ctl -D data/ -o "-p 5434" -l pg.log start  ./bin/psql --port 5434

3、導出PG10的 schema definitions

cd /usr/local/pgsql-10.10    ./bin/pg_dumpall -s  --port 5433 --no-subscriptions > ./schemadump.sql

4、 將PG10的 導出數據導入到PG11中

su - postgres   cd /usr/local/pgsql-11.5    ./bin/psql --port 5434 -d postgres -f /usr/local/pgsql-10.10/schemadump.sql

5、在源實例PG10中的每個數據庫中,創建一個捕獲所有表的發佈

注意:邏輯複製在每個數據庫中分別工作,因此需要在每個數據庫中重複。另一方面,您不必一次升級所有數據庫,因此可以一次完成一個數據庫,甚至不升級某些數據庫。

cd /usr/local/pgsql-10.10    ./bin/psql --port 5433    postgres=# c testdb1  testdb1=# CREATE PUBLICATION p_upgrade FOR ALL TABLES;  testdb1=#  dRp+                  Publication p_upgrade    Owner   | All tables | Inserts | Updates | Deletes   ----------+------------+---------+---------+---------   postgres | t          | t       | t       | t  (1 row)    testdb1=# c testdb2  testdb2=# CREATE PUBLICATION p_upgrade2 FOR ALL TABLES;  testdb2=#  dRp+                 Publication p_upgrade2    Owner   | All tables | Inserts | Updates | Deletes   ----------+------------+---------+---------+---------   postgres | t          | t       | t       | t  (1 row)

6、 在目標實例 PG11 中的每個數據庫中,創建訂閱剛剛創建的發佈的訂閱。確保與源數據庫和目標數據庫匹配正確。

su - postgres   cd /usr/local/pgsql-11.5   ./bin/psql --port 5434
testdb2=# c testdb1  testdb2=# CREATE SUBSCRIPTION s_sub CONNECTION 'host=192.168.2.4 port=5433 dbname=testdb1 user=repuser password=repuser' PUBLICATION p_upgrade;    testdb1=# dRs+                                                            List of subscriptions   Name  |  Owner   | Enabled | Publication | Synchronous commit |                                Conninfo                                   -------+----------+---------+-------------+--------------------+-------------------------------------------------------------------------   s_sub | postgres | t       | {p_upgrade} | off                | host=192.168.2.4 port=5433 dbname=testdb1 user=repuser password=repuser  (1 row)    testdb2=# c testdb2  testdb2=# CREATE SUBSCRIPTION s_sub2 CONNECTION 'host=192.168.2.4 port=5433 dbname=testdb2 user=repuser password=repuser' PUBLICATION p_upgrade2;    testdb2=# dRs+                                                             List of subscriptions    Name  |  Owner   | Enabled | Publication  | Synchronous commit |                                Conninfo                                   --------+----------+---------+--------------+--------------------+-------------------------------------------------------------------------   s_sub2 | postgres | t       | {p_upgrade2} | off                | host=192.168.2.4 port=5433 dbname=testdb2 user=repuser password=repuser  (1 row)

7、在PG10上,造些數據:

postgres=# c testdb1  testdb1=# insert into tb1(a,b,c) values (1,1,1),(2,2,2),(3,3,3);  testdb1=# insert into  tb2(a,b,c) values (1,1,1);

然後,到 PG11上的testdb1庫裏面,可以看到 數據已同步了。

8、後續如果在PG10上有加表操作,類似如下:

PG10上,我們加一個表  testdb1=# c testdb1  testdb1=# create table tb_new( a int ,b int );  testdb1=# insert into tb_new values(1,1) ,(2,2) ,(3,3),(4,4);    testdb1=# GRANT SELECT ON tb_new to repuser;    需要授權下    因為我們第五步的時候,給了all table做了複製的配置, 因此新加表後這裡不需要執行添加到發佈者的命令。    testdb1=# dRp+ p_upgrade  -- 查看發佈者的詳細信息                  Publication p_upgrade  Owner   | All tables | Inserts | Updates | Deletes   ----------+------------+---------+---------+---------   postgres | t          | t       | t       | t  (1 row)

PG10上加完表後,我們可以看到PG11上這個 tb_new 表是不存在的。 需要我們到PG11上手工創建下:

在PG11上執行如下命令:

c testdb1  create table tb_new( a int ,b int );  select count(*) from tb_new;   -- 這時候數據還是為0的    ALTER SUBSCRIPTION s_sub REFRESH PUBLICATION;  -- 刷新一下訂閱者    select count(*) from tb_new;   -- 這時候數據變成了4條了

9、 清除複製設置(在PG11新庫上執行)

c testdb1  DROP SUBSCRIPTION s_sub;    c testdb2  DROP SUBSCRIPTION s_sub2;

然後, 也可以刪除源實例PG10上的發佈,但這不是必需的。

10、最後,如果老的PG10上流量都切到PG11後,可以將PG10這個實例下線。

原生logical複製的限制【非常關鍵】: 

1、只支持普通表生效,不支持序列、視圖、物化視圖、外部表、分區表和大對象

關於邏輯複製不支持的事項的變通方法的一些附加註釋。如果您正在使用大型對象,則可以使用pg_dump移動它們,當然只要它們在升級過程中不會更改。這是一個重要的限制,因此如果您是大型對象的重度用戶,那麼此方法可能不適合您。如果您的應用程序在升級過程中發出TRUNCATE,則不會複製這些操作。也許您可以調整應用程序以防止它在升級時執行此操作,或者您可以替換DELETE。PostgreSQL 11將支持複製TRUNCATE,但這隻有在源和目標實例都是PostgreSQL 11或更新版本時才有效。

2、只支持普通表的DML(INSERT、UPDATE、DELETE)操作,不支持truncate、DDL操作

3、需要同步的表必須設置 REPLICA IDENTITY 不能為noting(默認值是default),同時表中必須包含主鍵,否則delete和update報錯

4、一個publisher可以包含一張或多張表,一張表可以有一個或多個publishers

5、一個發佈者可以有多個訂閱者訂閱,一個訂閱者也可以同時訂閱多個發佈者,在同一個數據庫下訂閱者不能對同一個發佈者的表重複訂閱(避免數據衝突)

6、邏輯複製不同於流複製,不是嚴格的主從關係,訂閱者端的普通表依然可以進行增刪改操作

7、同步表的表結構需要在發佈者和訂閱者兩邊保持一致(列的順序允許不一樣,但是列對應的數據類型必須一致)

8、如果訂閱者端的數據被誤刪,想要從發佈者重新copy同步表的數據,只能以重建同步表所在的訂閱者的方式來實現

其它注意事項:

publication – 發佈者

邏輯複製的前提是將數據庫 wal_level 參數設置成 logical;

源庫上邏輯複製的用戶必須具有 replicatoin 或 superuser 角色;

邏輯複製目前僅支持數據庫表邏輯複製,其它對象例如函數、視圖不支持;

邏輯複製支持DML(UPDATE、INSERT、DELETE)操作,TRUNCATE 和 DDL 操作不支持;

需要發佈邏輯複製的表,須配置表的 REPLICA IDENTITY 特性;

一個數據庫中可以有多個publication,通過 pg_publication 查看;

允許一次發佈所有表,語法: CREATE PUBLICATION alltables FOR ALL TABLES;

subscription – 訂閱者

訂閱節點需要指定發佈者的連接信息;

一個數據庫中可以有多個訂閱者;

可以使用enable/disable啟用/暫停該訂閱;

發佈節點和訂閱節點表的模式名、表名必須一致,訂閱節點允許表有額外字段;

發佈節點增加表名,訂閱節點需要執行: ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION

參考資料:

https://www.postgresql.org/docs/10/sql-createpublication.html

https://www.postgresql.org/docs/10/sql-createsubscription.html

https://www.postgresql.org/docs/10/sql-altersubscription.html

https://yq.aliyun.com/articles/585446?spm=a2c4e.11153940.0.0.48e86e272CVXQp

https://postgres.fun/20170528142004.html