논리적 디코딩

논리적 디코딩 (Logical Decoding)

이번 페이지에서는 PostgreSQL의 논리적 디코딩(logical decoding) — 47장 전체의 개요를 함께 살펴볼게요. "WAL에 저장된 변경을, 외부 소비자가 해석할 수 있는 형식으로 바꿔서 스트림으로 내보내는 인프라"가 무엇인지, 그리고 어떤 구성 요소로 이루어져 있는지 차근차근 설명해 드릴게요.

출처: PostgreSQL 공식 문서 — logicaldecoding

논리적 디코딩이란 무엇인가 (What logical decoding is)

PostgreSQL은 SQL로 수행된 수정 사항을 외부 소비자에게 스트림으로 내보내는 인프라스트럭처를 제공해요. 이 기능은 복제 솔루션과 감사(auditing)를 포함한 다양한 목적으로 쓰일 수 있어요.

변경 사항은 **논리적 복제 슬롯(logical replication slot)**으로 식별되는 스트림으로 전송돼요. 변경 사항이 스트리밍되는 **형식은 사용되는 출력 플러그인(output plugin)**이 결정해요. PostgreSQL 배포판에는 예시 플러그인이 제공되고, 핵심 코드를 수정하지 않고도 사용 가능한 형식의 선택을 넓히기 위해 추가 플러그인을 작성할 수 있어요.

모든 출력 플러그인은 INSERT가 만든 각 새 행과 UPDATE가 만든 새 행 버전에 접근할 수 있어요. UPDATEDELETE에 대한 이전(old) 행 버전의 가용성은 구성된 복제 식별자(REPLICA IDENTITY)에 따라 달라져요.

변경 사항은 스트리밍 복제 프로토콜을 사용하거나, SQL을 통해 함수를 호출하는 방식으로 소비할 수 있어요. 또 핵심 코드를 수정하지 않고 복제 슬롯의 출력을 소비하는 추가 방법을 작성할 수도 있어요.

논리적 디코딩 개념 (47.2 Logical Decoding Concepts)

**논리적 디코딩(logical decoding)**은 데이터베이스 테이블에 대한 모든 영구 변경을, 데이터베이스의 내부 상태에 대한 세부 지식 없이 해석할 수 있는 일관되고 이해하기 쉬운 형식으로 추출하는 과정이에요. PostgreSQL에서 논리적 디코딩은 저장 수준에서 변경을 설명하는 WAL(쓰기 전 로그)의 내용을, 튜플 스트림이나 SQL 문과 같은 애플리케이션 특정 형식으로 디코딩함으로써 구현돼요.

복제 슬롯(Replication Slots): 논리적 복제에서 슬롯은 원본 서버에서 만들어진 순서대로 클라이언트에 재생할 수 있는 변경 스트림을 나타내요. 각 슬롯은 단일 데이터베이스에서 일련의 변경을 스트리밍해요.

복제 슬롯 동기화 (Replication Slot Synchronization): 논리적 복제 슬롯을 스탠바이 서버에 동기화할 수 있으며, 동기화에 실패하면 그 예시 로그가 문서에 나와 있어요.

출력 플러그인 (Output Plugins): 슬롯에서 출력되는 데이터의 형식을 결정해요. 내보낸 스냅샷 (Exported Snapshots): 논리적 디코딩과 함께 스냅샷을 내보내는 기능도 있어요.

논리적 디코딩 예제 (47.1 Logical Decoding Examples)

SQL 인터페이스와 스트리밍 복제 프로토콜 두 가지로 논리적 디코딩을 제어하는 예시가 문서에 있어요. 논리적 디코딩을 사용하려면 먼저 wal_levellogical로, max_replication_slots를 적어도 1로 설정해야 해요. 그런 다음 대상 데이터베이스에 슈퍼유저로 연결해요.

스트리밍 복제 프로토콜 방식은 PostgreSQL 배포판에 포함된 pg_recvlogical 프로그램으로 시연해요. 이를 사용하려면 복제 연결을 허용하도록 클라이언트 인증을 설정해야 해요.

스트리밍 복제 프로토콜 인터페이스 (47.3 Streaming Replication Protocol Interface)

논리적 디코딩을 제어하는 프로토콜 명령이 있어요. 예를 들어 CREATE_REPLICATION_SLOT slot_name LOGICAL output_plugin, DROP_REPLICATION_SLOT slot_name [ WAIT ] 같은 명령들이죠. 자세한 내용은 스트리밍 복제 프로토콜 문서를 참고하세요.

논리적 디코딩 SQL 인터페이스 (47.4 Logical Decoding SQL Interface)

SQL 수준에서 논리적 디코딩과 상호작용할 수 있는 API에 대한 자세한 문서가 별도 절에 있어요. 한 가지 주의점: 동기 복제(synchronous replication)는 스트리밍 복제 인터페이스로 사용되는 복제 슬롯에서만 지원돼요. 함수 인터페이스와 추가 비핵심 인터페이스는 동기 복제를 지원하지 않아요.

pg_replication_slots 뷰와 pg_stat_replication 뷰는 각각 복제 슬롯과 스트리밍 복제 연결의 현재 상태에 대한 정보를 제공해요. 이 뷰들은 물리적 복제와 논리적 복제에 모두 적용돼요.

논리적 디코딩 출력 플러그인 (47.6 Logical Decoding Output Plugins)

예시 출력 플러그인은 PostgreSQL 소스 트리의 contrib/test_decoding 하위 디렉토리에서 찾을 수 있어요.

초기화 함수 (Initialization Function): 출력 플러그인은 플러그인 이름을 라이브러리 기본 이름으로 하는 공유 라이브러리를 동적으로 로드해서 불러와요. 필요한 출력 플러그인 콜백을 제공하고 라이브러리가 출력 플러그인임을 나타내려면 초기화 함수가 필요해요.

콜백 (Callbacks): begin_cb, change_cb, commit_cb 콜백은 필수이고, startup_cb, truncate_cb, message_cb, filter_by_origin_cb, shutdown_cb는 선택적이에요. truncate_cb가 설정되지 않았는데 TRUNCATE를 디코딩해야 한다면, 그 동작은 무시돼요.

기타: 출력 모드(Output Modes), 콜백 상세, 출력 생성 함수에 대한 자세한 설명이 문서에 있어요.

논리적 디코딩 출력 라이터 (47.7 Logical Decoding Output Writers)

논리적 디코딩에 출력 방법을 추가할 수 있어요. 기본적으로 세 가지 함수를 제공해야 해요 — WAL을 읽는 함수, 출력 작성 준비 함수, 출력을 쓰는 함수. 자세한 내용은 src/backend/replication/logical/logicalfuncs.c를 참고하세요.

논리적 디코딩의 동기 복제 지원 (47.8 Synchronous Replication Support for Logical Decoding)

논리적 디코딩으로, 스트리밍 복제의 동기 복제와 같은 사용자 인터페이스를 가진 동기 복제 솔루션을 구축할 수 있어요. 이렇게 하려면 스트리밍 복제 인터페이스로 데이터를 스트리밍해야 해요.

주의할 점(캐비엇): 논리적 디코딩으로 변경을 받는 동기 복제본은 단일 데이터베이스 범위에서 동작해요. 반면 synchronous_standby_names는 현재 서버 전체(server-wide)이므로, 데이터베이스가 여러 개라면 이 기법이 제대로 동작하지 않을 수 있어요. 또 동기 복제 설정에서 트랜잭션이 [사용자] 카탈로그 테이블을 배타적으로 잠그면 교착 상태(deadlock)가 발생할 수 있어요. 논리적 디코딩이 카탈로그에 접근하려고 카탈로그 테이블을 잠글 수 있기 때문이에요.

대형 트랜잭션 스트리밍 (47.9 Streaming of Large Transactions for Logical Decoding)

기본 출력 플러그인 콜백(begin_cb, change_cb, commit_cb, message_cb)은 트랜잭션이 실제로 커밋될 때만 호출돼요. 변경은 트랜잭션 로그에서 계속 디코딩되지만, 커밋 시점에만 출력 플러그인으로 전달돼요. 디코딩은 증분적으로 이뤄지고 메모리 사용을 제어하려고 디스크로 넘칠(spill) 수 있지만, 모든 디코딩된 변경은 최종 커밋 시점에 전송돼야 해요.

대형 트랜잭션으로 인한 **적용 지연(apply lag)**을 줄이려면, 출력 플러그인은 진행 중 트랜잭션의 증분 스트리밍을 지원하는 추가 콜백을 제공할 수 있어요. 여러 필수 스트리밍 콜백(stream_start_cb, stream_stop_cb, stream_abort_cb 등)이 있어요.

2단계 커밋 지원 (47.10 Two-phase Commit Support for Logical Decoding)

기본 출력 플러그인 콜백으로는 PREPARE TRANSACTION, COMMIT PREPARED, ROLLBACK PREPARED 같은 2단계 커밋 명령이 디코딩되지 않아요. PREPARE TRANSACTION은 무시되고, COMMIT PREPARED는 일반 커밋처럼 처리돼요.

2단계 명령의 스트리밍을 지원하려면 출력 플러그인이 추가 콜백(begin_prepare_cb, prepare_cb, commit_prepared_cb, rollback_prepared_cb, stream_prepare_cb 등)을 제공해야 해요. 이 2단계 커밋 디코딩 콜백이 제공되면, PREPARE TRANSACTION 시에 그 트랜잭션의 변경이 디코딩되어 출력 플러그인으로 전달되고 prepare_cb 콜백이 호출돼요.

더 알아보기 (Learn more)