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