PostgreSQL 邏輯複製

目前邏輯複製中兩點需要注意:

  1. 不支持DDL的同步,需要主庫與備庫手動執行
  2. 僅支持table的複製。其他對象不支持

配置發佈節點 - 主庫端

修改主庫配置參數

vi postgresql.conf配置文件

wal_level = replica
max_wal_senders = 10 
max_replication_slots = 8

創建邏輯複製用戶

[postgres@pg01 data]$ psql

create user luser
replication
login
connection limit 8
encrypted password '123456';

創建測試表

創建要複製的表,並插入一條測試數據

dong=# create table tlt (id int , name varchar(20));
CREATE TABLE

dong=# insert into tlt values (1 , 'logical');
INSERT 0 1

注意tlt表上,沒有主鍵

賦予select權限

將需要複製的表,授予select權限給複製用戶

dong=# grant select on tlt to luser;
GRANT

創建發佈

發佈該庫中的指定的表:

dong=# create publication pub1 for table tlt;

或者也可以發佈該庫中的所有表,包括以後在這個庫中新建的表:

dong=# create publication pub1 for all table ; 

查看發佈的表list

dong=# select * from pg_publication_tables;
 pubname | schemaname | tablename 
---------+------------+-----------
 pub1    | public     | tlt
(1 row)

查詢發佈狀態

dong=# select * from pg_publication;
  oid  | pubname | pubowner | puballtables | pubinsert | pubupdate | pubdelete | pubtruncate 
-------+---------+----------+--------------+-----------+-----------+-----------+-------------
 16464 | pub1    |       10 | f            | t         | t         | t         | t
(1 row)

配置訂閱節點 - 邏輯備庫端

修改備庫配置參數

vi postgresql.conf

[postgres@pg02 data]$ vi postgresql.conf
max_replication_slots = 8
max_logical_replication_workers = 4

重啓後生效

[postgres@pg02 data]$ pg_ctl  restart  

創建相應的庫

[postgres@pg02 data]$ createdb dong

創建需要複製的表結構

注意我這裏創建表的時候,並沒有創建到dong這個數據庫中(其實是不小心創建錯了,那就將錯就錯吧,看後邊會有什麼情況)

postgres=# create table tlt (id int , name varchar(20));
CREATE TABLE

創建訂閱

創建訂閱,必須使用pg的用戶纔可以

[postgres@pg02 data]$ psql

postgres=# create subscription sub1 connection 'host=192.168.56.103 port=5432 dbname=dong user=luser password=123456'
postgres-# publication pub1;
NOTICE:  created replication slot "sub1" on publisher
CREATE SUBSCRIPTION

在發佈節點(主)查看邏輯複製槽信息

postgres=# select slot_name , plugin , slot_type , database , active , restart_lsn
postgres-#   from pg_replication_slots;
   slot_name   |    plugin     | slot_type | database | active | restart_lsn 
---------------+---------------+-----------+----------+--------+-------------
 logical_slot1 | test_decoding | logical   | postgres | f      | 0/7F014FD0
 sub1          | pgoutput      | logical   | dong     | t      | 0/82000688
(2 rows)

在訂閱節點(備) 查看邏輯複製信息

postgres=# select * from pg_subscription;
  oid  | subdbid | subname | subowner | subenabled |                             subconninfo                              | subslotname | subsynccommit | subpublic
ations 
-------+---------+---------+----------+------------+----------------------------------------------------------------------+-------------+---------------+----------
-------
 24597 |   13830 | sub1    |       10 | t          | host=192.168.56.103 port=5432 dbname=dong user=luser password=123456 | sub1        | off           | {pub1}
(1 row)

檢查數據

發佈端

dong=# insert into tlt values (2,'data');
INSERT 0 1
dong=# 
dong=# 
dong=#  select * from tlt;
 id |  name   
----+---------
  1 | logical
  2 | data
(2 rows)

訂閱端

postgres=#  select * from tlt;
 id |  name   
----+---------
  1 | logical
  2 | data
(2 rows)

支持update、delete

我們之前買了一個伏筆,主庫的表沒有主鍵,那麼是無法同步update、delete操作的,並且主庫端也會報錯,如下:

dong=# update tlt set name='new date' where id=2;
ERROR:  cannot update table "tlt" because it does not have a replica identity and publishes updates
HINT:  To enable updating the table, set REPLICA IDENTITY using ALTER TABLE.

DDL操作是不能同步的,所以需要在兩個節點上分別創建主鍵。

dong=# alter table tlt add primary key(id);
ALTER TABLE
dong=# 

再次嘗試更新數據,成功

dong=# update tlt set name='new date' where id=2;
UPDATE 1

在接收端,查看是否有 new data

postgres=# select * from tlt;
 id |   name   
----+----------
  1 | logical
  2 | new date
(2 rows)

添加複製表

1 - 發佈:新建表

新建表

dong=# create table order_detail (id serial , 
dong(#     order_info varchar(20) , 
dong(#     order_date timestamp(0) with time zone) ;
CREATE TABLE

插入測試數據

dong=# insert into order_detail (id , order_date)
dong-# values (1, '2015-10-01');
INSERT 0 1

dong=# insert into order_detail (id , order_date)
dong-# values (1, '2021-10-01');
INSERT 0 1

查看測試表及數據

dong=# select * from order_detail;
 id | order_info |       order_date       
----+------------+------------------------
  1 |            | 2015-10-01 00:00:00+08
  1 |            | 2021-10-01 00:00:00+08
(2 rows)

2 - 發佈:賦權給複製賬戶

dong=# grant select on order_detail to luser;
GRANT

3 - 發佈:添加至已有的發佈

dong=# alter publication pub1 add table order_detail;
ALTER PUBLICATION

4 - 發佈:檢查

dong=# select * from pg_publication_tables;
 pubname | schemaname |  tablename   
---------+------------+--------------
 pub1    | public     | tlt
 pub1    | public     | order_detail
(2 rows)

5 - 訂閱:新建表

```sql
dong=# create table order_detail (id serial , 
dong(#     order_info varchar(20) , 
dong(#     order_date timestamp(0) with time zone) ;
CREATE TABLE


## 6 - 訂閱:刷新訂閱

```sql
postgres=# alter subscription sub1 refresh publication;
ALTER SUBSCRIPTION

7 - 訂閱:檢查

postgres=# select * from order_detail;
 id | order_info |       order_date       
----+------------+------------------------
  1 |            | 2015-10-01 00:00:00+08
  1 |            | 2021-10-01 00:00:00+08
(2 rows)

刪除複製表

發佈:在發佈中drop

alter publication pub1 drop table order_detail;

邏輯複製啓動、停止

訂閱節點啓動同步數據

alter subscription sub1 disable;

訂閱節點停止同步數據

alter subscription sub1 enable;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章