PG10 到 PG11 的邏輯複製
html
我下面演示的PG環境是單機多實例的方式部署在同一臺物理機上的。部署方式能夠參考 上一篇博客。sql
一、當前老的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 );
建立一個複製用的帳號
bash
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帳號的訪問地址,以下:
ide
host all repuser 192.168.2.1/24 md5
而後,reload下pg的配置。函數
二、初始化PG11新庫post
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
三、導出PG10的 schema definitionsspa
cd /usr/local/pgsql-10.10 ./bin/pg_dumpall -s --port 5433 --no-subscriptions > ./schemadump.sql
四、 將PG10的 導出數據導入到PG11中postgresql
su - postgres cd /usr/local/pgsql-11.5 ./bin/psql --port 5434 -d postgres -f /usr/local/pgsql-10.10/schemadump.sql
五、在源實例PG10中的每一個數據庫中,建立一個捕獲全部表的發佈orm
注意:邏輯複製在每一個數據庫中分別工做,所以須要在每一個數據庫中重複。另外一方面,您沒必要一次升級全部數據庫,所以能夠一次完成一個數據庫,甚至不升級某些數據庫。
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)
六、 在目標實例 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)
七、在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庫裏面,能夠看到 數據已同步了。
八、後續若是在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條了
九、 清除複製設置(在PG11新庫上執行)
\c testdb1 DROP SUBSCRIPTION s_sub; \c testdb2 DROP SUBSCRIPTION s_sub2;
而後, 也能夠刪除源實例PG10上的發佈,但這不是必需的。
十、最後,若是老的PG10上流量都切到PG11後,能夠將PG10這個實例下線。
原生logical複製的限制【很是關鍵】:
一、只支持普通表生效,不支持序列、視圖、物化視圖、外部表、分區表和大對象
關於邏輯複製不支持的事項的變通方法的一些附加註釋。若是您正在使用大型對象,則可使用pg_dump移動它們,固然只要它們在升級過程當中不會更改。這是一個重要的限制,所以若是您是大型對象的重度用戶,那麼此方法可能不適合您。若是您的應用程序在升級過程當中發出TRUNCATE,則不會複製這些操做。也許您能夠調整應用程序以防止它在升級時執行此操做,或者您能夠替換DELETE。PostgreSQL 11將支持複製TRUNCATE,但這隻有在源和目標實例都是PostgreSQL 11或更新版本時纔有效。
二、只支持普通表的DML(INSERT、UPDATE、DELETE)操做,不支持truncate、DDL操做
三、須要同步的表必須設置 REPLICA IDENTITY 不能爲noting(默認值是default),同時表中必須包含主鍵,不然delete和update報錯
四、一個publisher能夠包含一張或多張表,一張表能夠有一個或多個publishers
五、一個發佈者能夠有多個訂閱者訂閱,一個訂閱者也能夠同時訂閱多個發佈者,在同一個數據庫下訂閱者不能對同一個發佈者的表重複訂閱(避免數據衝突)
六、邏輯複製不一樣於流複製,不是嚴格的主從關係,訂閱者端的普通表依然能夠進行增刪改操做
七、同步表的表結構須要在發佈者和訂閱者兩邊保持一致(列的順序容許不同,可是列對應的數據類型必須一致)
八、若是訂閱者端的數據被誤刪,想要從發佈者從新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