PostgreSQL logical replication (publication / subscription)
PostgreSQL난이도: 고급소요 시간: 45–90분 (+ 초기 복사 시간)두 PostgreSQL cluster 사이의 테이블 단위 logical replication: wal_level=logical, replica identity 점검, publication과 subscription, 초기 동기화, 모니터링, 충돌(conflict) 처리, sequence 수동 동기화. 버전 간 이전(major upgrade, 서버 교체)에서 다운타임을 몇 초로 줄이는 최종 전환(cutover) 단계도 포함합니다.
Logical replication은 HA나 백업 수단이 아닙니다. cluster 전체의 동일한 사본과 failover에는 streaming replication 또는 Patroni를, 백업에는 pgBackRest를 사용합니다. 같은 서버에서의 제자리 major 버전 업그레이드(pg_upgrade)는 pg-major-upgrade에 있습니다.
구성: 서버 2대: 발행자(publisher) + 구독자(subscriber). 발행자는 단일 서버, streaming replication 또는 Patroni cluster일 수 있음
시나리오
- 지속 복제 (리포팅, 연동, 부분 사본) — 선택한 테이블이 다른 cluster로 계속 흘러갑니다(리포팅 서버, 데이터 웨어하우스 적재, 서비스 간 연동). 구독자는 쓰기 가능한 상태로 유지됩니다.
- 이전: 새 서버 / 새 major 버전 + 최종 전환(cutover) — 초 단위 다운타임으로 새 서버나 새 major 버전으로 전환: 초기 복사와 지속 동기화, 이어서 짧은 쓰기 중지와 최종 전환(cutover).
시작하기 전에
- 발행자에서 PostgreSQL …가 실행 중이고 … 데이터베이스가 있습니다.
- Patroni cluster …가 정상이고 …가 현재 Leader이며, replica에서 hot_standby_feedback = on입니다(pg-patroni 기본값).
- Standby …가 physical replication slot으로 primary에 연결되어 있습니다(primary_slot_name = …, pg-streaming의 slot 옵션). 이 slot이 없으면 slot 동기화가 동작하지 않습니다.
- 구독자에 PostgreSQL …가 pg-install로 설치되어 실행 중이며, 발행자에 있는 확장(PostGIS 등)의 …용 버전이 설치되어 있습니다.
- 구독자가 발행자의 …HAProxy/VIP 주소(…:…)…… 포트…에 접근할 수 있습니다(방화벽 / 보안 그룹).
- 발행자의 wal_level이 현재 어떤 값입니까? logical이 아니면 변경에 재시작이 필요하므로 유지보수 시간을 계획하십시오.
- 발행할 테이블에 primary key나 적절한 unique index가 있습니다. 없으면 발행자에서 UPDATE/DELETE가 오류를 냅니다. 목록에 나온 테이블에 PK를 추가하거나 replica identity를 정의하십시오(아래 단계).
- Logical replication은 DDL을 전달하지 않으며(CREATE/ALTER TABLE), sequence 값과 large object도 전달하지 않습니다. 복제 기간 동안 스키마 변경은 먼저 구독자에, 그다음 발행자에 수동으로 적용합니다. 팀에 알렸습니다.
- 발행자에 WAL용 추가 디스크 여유가 있습니다. 구독자가 멈추면 slot이 WAL을 쌓습니다(한도: … GB).
가이드 단계
- 발행자 준비 — 발행자가 …Leader…primary…인지 확인 · Logical replication 설정 기록 · Logical replication 설정을 Patroni에 기록 · 발행자 재시작 · Patroni 멤버 재시작 · 복제 사용자 생성 …
- Replica identity — PK 없는 테이블 목록 · PK 없는 테이블에 replica identity 정의
- Publication — Publication 생성
- 구독자 준비 — 구독자 worker 설정 기록 · 구독자 재시작 · 발행자 비밀번호를 .pgpass에 기록 · 데이터베이스와 스키마 생성 · Role과 권한 옮기기
- Subscription과 초기 동기화 — Subscription 생성 · 초기 동기화 완료 대기 · 데이터 건수 비교 · 실시간 변경 테스트
- Failover 시 slot 보존 — Patroni에서 slot을 영구(permanent)로 정의 · Replica에서 slot이 보이는지 확인 · Primary: 동기화 standby slot 정의 · Standby: slot 동기화 켜기 · Failover 후 구독을 새 primary로 전환 · Failover 후 구독 재구성
- 모니터링 — 구독 상태 (구독자) · Slot 지연 (발행자)
- 충돌(conflict) 처리 — 오류 찾기 · 구독자에서 충돌 행 수정 · 충돌 트랜잭션 건너뛰기
- Sequence 동기화 — Sequence 값을 발행자에서 구독자로 옮기기
- 마지막 전환 (cutover) — 발행자에서 쓰기 중지 · 마지막 변경 사항 전송 확인 · Sequence 마지막 동기화 · 구독 제거 · 통계 수집 · 애플리케이션을 구독자로 전환 …
- 유지보수 작업 — 새 테이블 추가 · 스키마 변경 (ALTER TABLE) · 구독 제거 (발행자에 접근할 수 없을 때)