이번 문서에서는 PostgreSQL 16 Release New Feature 중 Replication에 대한 내용을 다룹니다.
Logical Replication From Standby Server
PostgreSQL 15 버전까지는 Primary Server에서만 Logical Replication의 게시(Publication)을 구성할 수 있었습니다. Replication이 다중으로 구성되어 있다면 그 만큼 Primary Server의 부하도 증가합니다.
PostgreSQL 16 버전부터는 Standby Server에서 게시(Publication)을 구성할 수 있습니다. 이 기능을 통해 Primary Server의 Replication 부하를 감소 시킬 수 있습니다.
📢 Primary → Physical Replication → Standby → Logical Replication → Standby 구성은 PostgreSQL 16 버전부터 구성 가능합니다.
📢 Primary → Logical Replication → Standby → Logical Replication → Standby 구성은 PostgreSQL 16 버전 이하에서도 구성 가능합니다.
📢 설명의 용이성을 위하여 Primary, Standby, Slave로 서버 구분을 하였습니다.
Standby Server에 Logical Replication 구성
PostgreSQL 16 버전부터는 Standby Server에서 Logical Replication 구성이 가능 합니다. 이러한 구성을 위해서는 Primary Server는 wal_level = logical로 설정 되어 있어야 합니다.
Primary Server Replication 설정
-- Replication Role 생성
-- physicaluser : Physical Replication(Streaming) / logicaluser : Logical Replication
CREATE ROLE physicaluser WITH REPLICATION LOGIN PASSWORD 'physicaluser' ;
CREATE ROLE logicaluser WITH REPLICATION LOGIN PASSWORD 'logicaluser' ;
-- 게시(Publication) 생성
CREATE PUBLICATION my_publication FOR TABLE repltab ;
GRANT SELECT ON TABLE repltab TO logicaluser ;
📢 Standby Server Read-Only로 DDL 수행이 불가 하기 때문에 Primary Server에서 Logical Replication Role과 게시(Publication)을 생성합니다. 생성된 Role과 게시(Publication)는 Streaming Replication을 통해 Standby Server에 적용됩니다.
-- Physical Replication Slot 생성
SELECT pg_create_physical_replication_slot( 'pslot1' ) ;
## pg_hba.conf 설정
host replication physicaluser 10.10.45.241/32 trust
-- PostgreSQL 15 버전에서 구독(Subscription) 생성 불가
CREATE SUBSCRIPTION my_subscription CONNECTION 'dbname=postgres host=10.10.45.241 port=5432 user=logicaluser password=logicaluser' PUBLICATION my_publication ;
ERROR: could not create replication slot "my_subscription": ERROR: logical decoding cannot be used while in recovery
-- [Slave] 구독(Subscription) 생성 시 Hang 상태처럼 표시
-- Hang 상태는 아니며, Priamry Server로 부터 메시지를 대기하는 상태
CREATE SUBSCRIPTION my_subscription CONNECTION 'dbname=postgres host=10.10.45.241 port=5432 user=logicaluser password=logicaluser' PUBLICATION my_publication ;
-- [Primary] Primary Server에서 pg_log_standby_snapshot() Function 수행
SELECT pg_log_standby_snapshot() ;
pg_log_standby_snapshot
-------------------------
0/71000098
-- [Slave] Subscription 생성 완료
NOTICE: created replication slot "my_subscription" on publisher
CREATE SUBSCRIPTION
📢 pg_log_standby_snapshot() Function bgwriter나 Checkpointer가 WAL에 기록을 기다릴 필요 없이 실행 중인 트랜잭션의 Snapshot을 찍어 WAL에 기록합니다. 즉, Logical Replication Slot 생성 속도를 높이기 위해 이 함수를 사용할 수 있습니다.
PostgreSQL 16 버전에서 Parallel Apply Worker에 의한 Logical Replication이 가능합니다. 구독(Subscription) 생성 시 streming = parallel 옵션이 추가 되었습니다. 이로 인해 pg_subscription Catalog의 컬럼의 변화도 있습니다.
구분
Column
Description
수정
substream
Data Type이 boolean → char로 변경 f : 진행중인 트랜잭션의 Streming을 허용하지 않음 t : 진행중인 트랜잭션의 Streming을 허용 p : 사용 가능한 경우 Parallel Apply Worker를 통해 직접 변경사항 적용(사용 가능한 Parallel Apply Worker가 없는 경우 t와 동일)
추가
subpasswordrequired
인증을 위한 비밀번호 필요 여부
추가
subrunasowner
Subscription Owner의 권한으로 Subscription 사용 여부
추가
suborigin
none : Local에서만 생성된 데이터 전송 any : Local + Replication으로 생성된 데이터 전송
SELECT subname , substream FROM pg_subscription ;
subname | substream
-----------------+-----------
my_subscription | p
양방향 Logical Replication
PostgreSQL 16 버전 부터 양방향 Logical Replication이 가능합니다. 즉, Node 1은 Node 2에서 변경된 내용을 수신하여 적용하고 Node 1에서 변경된 내용을 Node 2로 전송하여 적용 시킬 수 있습니다. 반대로 Node 2는 Node 1에서 변경된 내용을 수신하여 적용하고 Node 2에서 변경된 내용을 Node 1으로 전송하여 적용 시킬 수 있습니다. 양방향 Logical Replication을 통해 두 Node 중 하나에서 수행된 모든 수정 사항을 두 Node 모두에 미러링되어 동기화 할 수 있습니다.
PostgreSQL 15 버전 까지는 이 기능을 지원하지 않기 때문에 Apply Worker는 데이터가 Local에서 생성되었는지 Replication을 통해 생성되었는지 알지 못합니다. 따라서 아래와 같은 무한 루프 상태가 됩니다.
Node 1에서 변경된 내용을 Node2로 전송 → Node2 데이터 적용
Node 2에서 변경된 내용을 Node1으로 전송 → Node1 데이터 적용
1 → 2 → 1 → 2 → 1 → 2 → ... 무한 루프 발생
PostgreSQL 16에서 Subscription 생성 Syntax에 origin 파라미터가 도입되어 Apply Worker는 데이터가 Local에서 생성되었는지 Replication을 통해 생성되었는지 알 수 있게 되어 무한 루프 상태가 발생하지 않습니다.
댓글