본문으로 건너뛰기

12.4 로지컬 복제

Logical replication은 PG 10에서 정식 도입된 행 단위·테이블 단위 복제입니다. WAL을 decode해 SQL-level의 변경을 publisher → subscriber로 보냅니다. 메이저 버전이 달라도 동작, 일부 테이블만 가능, 단방향·다방향 모두. 스키마 변경 무중단 적용·CDC·메이저 업그레이드 무중단 같은 시나리오의 핵심입니다.

physical vs logical 비교

측면physical (streaming)logical
단위페이지·WAL byte행·테이블
subscriber 상태읽기 전용읽기·쓰기
버전 일치primary == standby다른 메이저도 OK
일부 테이블만불가가능
스키마자동 동기화수동 — DDL은 별도
TRUNCATE자동publication 옵션
LOB 한계없음DDL·sequence·LO 미지원

활성

publisher

# postgresql.conf
wal_level = logical
max_replication_slots = 10
max_wal_senders = 10

restart 필요 (wal_level은 postmaster 컨텍스트).

-- 권한
CREATE ROLE repl_user LOGIN REPLICATION PASSWORD 'secret';
GRANT SELECT ON ALL TABLES IN SCHEMA public TO repl_user;

pg_hba.conf:

hostssl  app_main  repl_user  10.0.0.0/8  scram-sha-256
hostssl  replication  repl_user  10.0.0.0/8  scram-sha-256

publication

-- 전체 DB의 모든 테이블
CREATE PUBLICATION pub_all FOR ALL TABLES;

-- 특정 테이블
CREATE PUBLICATION pub_orders FOR TABLE orders, order_items;

-- 스키마 단위 (PG 15+)
CREATE PUBLICATION pub_app FOR TABLES IN SCHEMA app;

-- 필터링 (PG 15+)
CREATE PUBLICATION pub_kr FOR TABLE orders WHERE (country = 'KR');

-- 컬럼 리스트 (PG 15+)
CREATE PUBLICATION pub_basic FOR TABLE users (id, name);

subscriber

-- subscriber 쪽에서 — 같은 이름의 빈 테이블 미리 생성
CREATE TABLE orders (...);

-- subscription
CREATE SUBSCRIPTION sub_orders
  CONNECTION 'host=primary.example.com dbname=app_main user=repl_user password=secret sslmode=require'
  PUBLICATION pub_orders;

이걸로 initial sync(테이블의 현재 내용 복사) + streaming(이후 변경 전달)이 시작됩니다.

동작 흐름

    flowchart LR
  PG1["publisher<br/>PostgreSQL"]
  DEC["walsender +<br/>logical decoding"]
  SUB["subscriber<br/>worker"]
  APP["apply 적용"]
  PG2["subscriber<br/>PostgreSQL"]

  PG1 -- "WAL" --> DEC
  DEC -- "row 단위 메시지" --> SUB
  SUB --> APP --> PG2

  classDef pub fill:#ede9fe,stroke:#6d28d9,color:#3b0764
  classDef sub fill:#d1fae5,stroke:#047857,color:#064e3b
  classDef mid fill:#dbeafe,stroke:#1d4ed8,color:#1e3a8a
  class PG1 pub
  class PG2 sub
  class DEC,SUB,APP mid
  

publisher는 logical replication slot을 하나 만들어 이 subscription의 lsn까지 WAL 보존. subscriber가 끊겨도 다시 잇기 가능합니다.

표준 시나리오

1. 메이저 업그레이드 무중단

1. 새 메이저(v18)에 빈 클러스터 + 스키마 dump 복원
2. v17(현 운영) → v18 logical replication 시작
3. initial sync + 따라잡음
4. 짧은 점검 시간에 운영 트래픽을 v18로 전환
5. v17 정지

자세한 절차는 18.4.

2. 데이터 분석용 ETL 대체

-- 데이터웨어하우스가 OLTP의 변경을 실시간 받음
CREATE SUBSCRIPTION sub_etl ... PUBLICATION ...;

ETL job 대신 상시 동기화합니다.

3. 멀티 마스터 (활성 두 사이트)

PG 코어는 단일 마스터 복제만 — 양방향은 EDB의 BDR이나 PGD 같은 상용 솔루션이 필요합니다. 단순 양방향은 데이터 충돌 위험 크니 신중히 진행합니다.

한계와 함정

DDL은 자동 안 됨

-- publisher
ALTER TABLE orders ADD COLUMN priority int;

-- subscriber는 같은 ALTER가 자동으로 안 됨

운영자가 스키마 변경을 양쪽에 같은 순서로 수동 적용해야 합니다. PG 17부터 일부 자동화가 들어왔지만 완전한 DDL 동기화는 아직.

sequence 안 됨

INSERT INTO orders DEFAULT VALUES;
-- publisher의 sequence는 1, 2, 3 ...
-- subscriber에 row는 가지만 subscriber sequence는 갱신 안 됨

failover 시 subscriber sequence를 수동으로 보정해야 합니다. PG 16+에서 일부 개선합니다.

충돌 처리

같은 row를 양쪽이 동시에 바꾸면 충돌. 단방향 복제에서는 subscriber의 변경이 있으면 안 됩니다.

ERROR:  duplicate key value violates unique constraint "..."

ALTER SUBSCRIPTION sub DISABLE 후 수동 정리 → ENABLE.

large object·TRUNCATE·view·시퀀스 ownership

  • LO 미지원 — bytea 사용 권장
  • TRUNCATE는 PG 11+부터, publication 옵션으로
  • view는 정의만 가능, 데이터는 underlying table
  • 시퀀스 ownership 안 따라옴

REPLICA IDENTITY

UPDATE/DELETE 시 publisher가 어떤 키로 row를 식별할지 정해야 합니다.

REPLICA IDENTITY의미
DEFAULT (기본)PK 사용
FULL모든 컬럼을 키로 — PK 없는 테이블
USING INDEX특정 unique 인덱스
NOTHINGUPDATE/DELETE 복제 안 됨

PK 있는 테이블은 자동, 없으면:

ALTER TABLE no_pk_table REPLICA IDENTITY FULL;

FULL은 모든 컬럼이 WAL에 기록되어 WAL 양 증가합니다. 가능하면 PK 사용합니다.

모니터링

-- publisher 측
SELECT * FROM pg_replication_slots WHERE slot_type = 'logical';
SELECT * FROM pg_stat_replication;

-- subscriber 측
SELECT subname, received_lsn, latest_end_lsn, latest_end_time
  FROM pg_stat_subscription;
신호점검
pg_replication_slots.confirmed_flush_lsn 진행 안 됨subscriber 적용 멈춤
publisher xmin/catalog_xmin 고정vacuum 막힘 → BLOAT
pg_stat_subscription_statssync_error_count충돌 발생

운영 안티패턴

안티패턴위험
sub가 멈춰 있는데 모르고 둠publisher BLOAT 폭증
DDL을 한쪽만 적용다음 DML에서 sub 실패
sequence 갱신 무시failover 후 PK 충돌
같은 row를 양쪽에서 변경unique violation 충돌
LOB 컬럼 있는 테이블을 logical로데이터 누락
Logical replication은 상시 monitoring이 필수. publisher의 pg_replication_slots가 잡고 있는 catalog_xmin이 멈춰 있으면 운영 클러스터 전체가 vacuum 못 도는 사고로 이어집니다.

정리

  • logical replication = 행·테이블 단위 복제. 메이저 버전 다름·일부 테이블만 가능
  • publication + subscription 모델
  • DDL·sequence·LO는 자동 안 됨 — 수동 처리 필요
  • REPLICA IDENTITY 설정 (PK 권장, FULL은 비용 큼)
  • 표준 시나리오: 메이저 업그레이드 무중단, ETL 대체
  • catalog_xmin·sync_error 모니터링 필수

다음 절(12.5)에서는 가장 표준적인 HA 도구 — Patroni를 봅니다.