前言
Postgresql支持“邏輯”和“物理”兩種復制方式,邏輯復制是一種基於數據對象的復制標識(通常是主鍵)復制數據對象及其修改的方法,而后者使用准確的塊地址以及逐字節的復制方式(WAL日志),邏輯復制允許數據復制和安全性上更細粒度的控制(可以對特定表進行復制)。邏輯復制采用發布者->訂閱者模型,具體流程結構圖如下:
邏輯復制的能力:
1、一個數據庫或者一個數據庫子集發生更改時,把增量的改變發送給訂閱者。
2、在更改到達訂閱者時引發觸發器。
3、把多個數據庫聯合到單一數據庫。
4、在Postgresql不同主版本之間進行復制。
5、在不同的平台(例如Linux到Windows)的Postgresql實例之間復制。
6、將復制數據的訪問給予不同的用戶組。
7、在多個數據庫之間共享數據庫的子集。
8、Pubilcation可以選擇把它們產生的更改限制為INSERT、UPDATE、DELETE及UPDATE的任意組合。
9、表的列通過名稱匹配。訂閱表中的列順序不需要與發布表順序一致;列的數據類型也不需要一樣,只要可以將數據的文本表示轉換為目標類型即可,如:int列復制到bigint列,此外目標表還可以具備發布表中不存在的額外列,額外列將以定義的默認值填充。
邏輯復制限制:
1、一個訂閱被刪除並且重建時,同步信息會丟失,數據必須重新同步。
2、表在發布者和訂閱者之間使用完全限定的表名進行匹配,不支持復制到訂閱者上命名不同的表,同時列名也必須匹配不能映射。
3、采用復制槽的方式,當存在沖突時,復制會暫停,需要人工處理,可能導致發布節點WAL日志積壓嚴重,嚴重情況下導致發布節點不可用。
4、數據庫模式和DDL命令不會被復制
5、序列數據不被復制
6、大對象不會被復制
7、復制只能是普通表,不能是視圖、物化視圖、分區根表或者外部表;如果是分區,可以一一對應地復制分區層次,但當前不能復制成一種不同的分區設置。
8、支持TRUNCATE但是當使用cascade清空,而表存在外鍵類鏈接時,如果受影響的表屬於同一訂閱,這會正確工作,但是不屬於同一訂閱的表時,會報錯。
9、要求PG9.4及以上版本
10、復制表需要有主鍵、或者唯一性約束,否則只能設置replica identity補全日志
11、復制用戶權限需要replication或superuser權限
快速部署
1、修改發布者postgres.conf文件
wal_level = logical
max_wal_senders = 100
2、發布者節點創建用戶
#以public模式為例
create user repl replication with password 'repl'; alter user repl set default_transaction_read_only=on; grant USAGE on SCHEMA public to repl; grant SELECT on ALL tables in schema public to repl; alter default privileges in schema public grant select on tables to repl;
3、修改發布者節點pg_hba.conf文件
host all repl 訂閱者IP/32 md5
4、重啟PG
su - postgres -c "pg_ctl restart"
5、發布者節點創建發布
create publication pub1 for table tab1; --alter table tab1 replica identity full; --無主鍵或者唯一性約束時開啟補全日志,此時會導致復制效率很低
6、訂閱者節點
#max_replication_slots需要設置
#max_logical_replication_workers需要設置
#max_worker_processes需要設置
#創建表結構
create subscription pub1 connection 'host=發布者IP post=5432 dbname=postgres user=repl password=repl' publication pub1; alter subscription pub1 refresh publication;
運維監控
alter publication pub1 add table test.tab1;#從節點需要刷新才能看到新添加表 alter subscription pub1 refresh publication; #刷新訂閱 drop pubilcation pub1; #刪除發布 select * from pg_pubilcation;#發布 select * from pg_pubilcation_tables;#發布哪些表 select * from pg_stat_subscription;#復制進度 select * from pg_subscription; #訂閱 select *,srrelid::regclass from pg_subscription_rel; #訂閱哪些表 drop subscription pub1;#刪除訂閱
沖突處理
update或delete操作時可能會導致沖突,這時可以查看日志剛剛訂閱者上的數據,或者使用pg_replication_origin_advance()函數跳過該事務。