본문으로 건너뛰기
18.4 로지컬 복제 기반 무중단 업그레이드

18.4 로지컬 복제 기반 무중단 업그레이드

pg_upgrade --link도 수 분의 다운타임이 발생합니다. 메이저 업그레이드 다운타임을 초 단위까지 줄이려면 logical replication 기반 절차를 씁니다.

큰 그림

    flowchart LR
  OLD["옛 17 primary<br/>(publisher)"]
  NEW["새 18 cluster<br/>(subscriber)"]
  APP["application"]

  OLD -- "logical replication" --> NEW
  APP -- "1. read·write 옛" --> OLD
  APP -- "2. read·write 새 (cutover)" --> NEW

  classDef old fill:#fed7aa,stroke:#c2410c,color:#7c2d12
  classDef new fill:#d1fae5,stroke:#047857,color:#064e3b
  classDef app fill:#dbeafe,stroke:#1d4ed8,color:#1e3a8a
  class OLD old
  class NEW new
  class APP app
  

표준 절차

1. 새 18 클러스터 준비 (initdb·설정)
2. 옛 클러스터의 스키마를 새 클러스터에 복원 (`pg_dump --schema-only`)
3. logical replication 활성 (publication + subscription)
4. 초기 sync 완료 대기 — 큰 DB는 수 시간
5. CDC 실시간 동기화 진행
6. 점검 시간 — application의 connection을 새 클러스터로 cut-over (분 단위)
7. 새 클러스터가 primary로 동작 검증
8. 옛 클러스터 _read-only_ 일정 기간 유지
9. 옛 클러스터 decommission

1단계 — 새 클러스터 준비

# 새 18 클러스터 initdb
sudo -u postgres /usr/pgsql-18/bin/initdb -D /var/lib/pgsql/18/data \
  --encoding=UTF8 --locale=C.UTF-8 --data-checksums

# wal_level·max_replication_slots 등 설정
cat << 'EOF' >> /var/lib/pgsql/18/data/postgresql.conf
wal_level = logical
max_replication_slots = 10
max_wal_senders = 10
max_logical_replication_workers = 10
EOF

sudo systemctl start postgresql-18

2단계 — 스키마 복제

# 옛 (PG 17)에서 스키마만 dump
pg_dump --schema-only --no-publications --no-subscriptions \
  -h old-pg -U postgres app_main > schema.sql

# 새 (PG 18)에 복원
psql -h new-pg -U postgres -d app_main -f schema.sql

--schema-only로 데이터 없이 구조만. 새 클러스터의 스키마가 완벽히 동일해야 logical 시작합니다.

3단계 — publication·subscription

-- 옛 (publisher)
CREATE PUBLICATION pub_all FOR ALL TABLES;

-- 새 (subscriber)
CREATE SUBSCRIPTION sub_all
  CONNECTION 'host=old-pg dbname=app_main user=repl_user password=secret'
  PUBLICATION pub_all;

CREATE SUBSCRIPTION이 자동으로 initial sync 시작합니다.

4단계 — 초기 sync 대기

-- 새 클러스터에서
SELECT subname, subenabled, subskiplsn,
       (SELECT pg_size_pretty(pg_database_size(current_database())))
  FROM pg_subscription;

SELECT subname, relname, srsubstate, srsublsn
  FROM pg_subscription_rel sr
  JOIN pg_subscription s ON sr.srsubid = s.oid
  JOIN pg_class c ON sr.srrelid = c.oid
 ORDER BY srsubstate;
srsubstate의미
iinitial
ddata being copied
ssynced
rready (streaming)

모든 테이블이 r이 되면 CDC만 진행합니다. 큰 DB는 몇 시간 걸림.

5단계 — CDC 진행 확인

-- 옛에서
SELECT slot_name, active, pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), confirmed_flush_lsn)) AS lag
  FROM pg_replication_slots;

-- lag가 작은 상태 유지면 OK

이 시점 옛 클러스터에 계속 트래픽, 새 클러스터는 뒤따라 적용합니다.

6단계 — application cutover

가장 중요한 단계. 다운타임 결정합니다.

1. application 쓰기를 옛에 잠시 차단 (read-only 또는 trickle)
2. 옛의 모든 변경이 새에 적용된 것 확인 (lag = 0)
3. 새 클러스터에서 sequence 갱신 — logical은 sequence 동기 안 됨
4. application connection string을 새 클러스터로 변경
5. 트래픽 시작

sequence 동기화

-- 옛에서 모든 sequence 값
SELECT 'SELECT setval(''' || sequencename || ''', '
  || last_value || ');' AS cmd
  FROM pg_sequences;

새 클러스터에서 실행해 sequence 값 같게 설정합니다.

connection string 변경

방법메모
application 재배포다운타임 짧음
DNS record 변경TTL에 따라
HAProxy 등 라우터즉시
pgBouncer 설정 변경즉시

운영 권장: pgBouncer로 두 클러스터 동시에 정의해 두고 config switch.

7단계 — 검증

  • 모든 application healthcheck
  • 새 클러스터에서 writes 정상
  • 옛 클러스터는 이제 read-only
-- 옛에서
ALTER DATABASE app_main SET default_transaction_read_only = on;
SELECT pg_reload_conf();

8단계 — 정리

  • 1~2주 옛 클러스터 유지 (롤백 대비)
  • 충분히 안정 확인 후 decommission
-- 새 클러스터에서 subscription 제거
DROP SUBSCRIPTION sub_all;

-- 옛 클러스터의 publication 제거
DROP PUBLICATION pub_all;

한계와 주의

logical replication의 한계(12.4)가 그대로 적용:

항목메모
sequence수동 갱신 필수
DDL자동 동기 안 됨 — 마이그레이션 중 DDL 회피
Large Object미지원 — bytea로
일부 테이블 미지원unlogged, temp, system catalog
replica identityPK 또는 FULL 필수 (12.4)
application의 sequence 의존nextval 호출 시 새 클러스터에서 충돌 위험

확장 호환성

# 새 클러스터에도 같은 확장 설치
sudo dnf install -y pgvector_18 pg_partman_18
-- 새 클러스터에서
CREATE EXTENSION pgvector;
CREATE EXTENSION pg_partman;
-- ...

매니지드 클라우드

AWS RDS·Aurora·Azure Flexible Server 등 Blue/Green Deployment 기능이 자동화된 logical replication 업그레이드:

aws rds create-blue-green-deployment \
  --source arn:aws:rds:...:db:mydb \
  --target-engine-version 18.0

매니지드가 자동 logical 셋업·sync·cutover를 제공합니다. 운영자 부담 ↓.

다운타임 추정

시나리오다운타임
application 재배포30초~수 분
pgBouncer config switch< 10초
DNS record + 짧은 TTL< 1분
HAProxy 자동 전환< 5초

CDC가 잘 따라잡으면 사용자가 인지하지 못하는 수준까지 가능합니다.

실패 시 롤백

cut-over 후 사고 발견하면:

  1. application connection을 옛 클러스터로 복원
  2. 새 클러스터에서 진행된 짧은 트래픽은 손실 (또는 reverse logical replication 시도 — 어려움)
  3. 사고 분석 후 재시도

옛 클러스터를 2주 이상 유지해야 안전합니다.

정리

logical replication을 쓰면 메이저 업그레이드 다운타임을 초 단위까지 줄일 수 있습니다. 절차는 스키마 dump → publication·subscription → initial sync → CDC → cut-over로 이어지며, sequence는 수동으로 갱신하고 DDL은 업그레이드 중에 회피합니다.

  • pgBouncer 또는 HAProxy로 빠르게 cut-over합니다
  • 매니지드 클라우드의 Blue/Green이 이 과정을 자동화합니다
  • 옛 클러스터는 1~2주 유지해 롤백에 대비합니다