PostgreSQL 14에서 XNUMX단계 커밋의 논리적 디코딩 텍스트

업데이트: 2년 2023월 XNUMX일

PostgreSQL 14에서 XNUMX단계 커밋의 논리적 디코딩 텍스트

Fujitsu OSS 팀과 PostgreSQL 오픈 소스 커뮤니티는 PG14의 논리적 복제에서 XNUMX단계 커밋을 해독하는 기능을 추가하기 위해 협력했습니다. 어떤 기능인지 살펴볼까요?

배경

XNUMX단계 커밋은 트랜잭션이 XNUMX단계로 커밋되는 메커니즘입니다. 일반적으로 일관성을 보장하기 위해 분산 데이터베이스에서 사용됩니다. 트랜잭션의 두 단계는 PREPARE 단계와 COMMIT/ROLLBACK 단계입니다. PG에서 두 단계로 제출된 명령은 다음과 같습니다.

거래 준비

커밋 준비

롤백 준비

PG는 이미 버전 8.0에서 10.0단계 커밋을 지원하고 버전 XNUMX은 논리적 복제를 지원합니다. 그러나 논리적 복제에서는 XNUMX단계 커밋이 지원되지 않습니다. PREPARE TRANSACTION, COMMIT PREPARED 및 ROLLBACK PREPARED 명령은 단일 인스턴스에서 지원되었지만 이러한 명령을 대기 시스템에 논리적으로 복사해야 하는 경우 더 이상 원래 의미를 유지하지 않습니다. PREPARE TRANSACTION 명령은 NOP로 처리되며 전혀 디코딩되지 않습니다. COMMIT PREPARED 명령은 COMMIT로 간주되고 ROLLBACK PREPARED 명령은 ABORT로 간주됩니다.

XNUMX단계 커밋이란

XNUMX단계 커밋은 분산 데이터베이스 간의 일관성을 유지하는 데 도움이 되는 원자적 커밋 프로토콜입니다. 데이터베이스 내에서 원자성을 제공하는 일반 커밋은 데이터베이스 간 트랜잭션에 일관성을 제공하기에 충분하지 않습니다. 이 문제를 설명하기 위해 예를 들어보겠습니다.

1) John은 A 은행에 300$를 가지고 있습니다.

2) Mark는 B 은행에 100$을 가지고 있습니다.

3) John은 Mark에게 100$를 송금하려고 합니다.

거래 중에 은행 A에서 은행 B로 100$를 인출해야 합니다. 거래가 끝나면 200$가 있어야 합니다. 이체 과정 중 언제든지 거래가 실패하면 계좌 상태를 이체 시작 전 상태로 복원해야 합니다. 다양한 이유로 거래가 실패할 수 있습니다. 트랜잭션이 커밋되기 전에 중단이 발생하면 트랜잭션이 롤백됩니다. 이 예에서 John의 계정이 차감될 때 중단이 발생하면 중단 포트에 대한 John의 계정이 줄어들지 않아야 합니다. 이것이 간단한 커밋이 데이터베이스 내에서 일관성을 유지하는 방법입니다.

그러나 우리는 그러한 상황, 즉 John의 계좌에서 100$를 빼는 거래는 한 번의 제출로 성공하지만 Bank B에 있는 Mark의 계좌에 100$를 추가하는 거래는 실패하고 롤백되는 상황을 고려합니다. 이 작업이 끝난 후 John의 계정이 인출되었지만 Mark는 금액을 받지 못합니다. 100$가 사라졌습니다. 분산 트랜잭션을 처리할 때 단순 커밋이 실패할 수 있습니다.

분산 트랜잭션의 단계별 실행

XNUMX단계 커밋의 경우 데이터베이스 중 하나가 분산 트랜잭션의 조정자 역할을 합니다.

무대 1

데이터베이스는 트랜잭션을 적용하기 시작한 다음 준비합니다. 준비된 트랜잭션을 준비 메시지 형태로 다른 데이터베이스에 보냅니다. 두 번째 데이터베이스는 준비 메시지를 받은 다음 트랜잭션을 준비합니다. 준비는 트랜잭션의 변경 사항을 포함하지만 커밋하지는 않습니다. 더티 데이터는 지속성을 위해 디스크에 기록됩니다. 모든 데이터베이스가 트랜잭션을 준비하고 트랜잭션에 대한 모든 정보가 디스크에 저장되면 준비 단계가 완료됩니다.

무대 2

다음으로 중재자는 커밋 단계를 시작합니다. 두 번째 데이터베이스가 어떤 이유로 트랜잭션을 준비하지 못하면 중재자는 롤백 단계를 시작합니다. 따라서 준비의 성공 여부에 따라 트랜잭션이 커밋되거나 롤백됩니다. 필요한 준비 트랜잭션이 디스크에 기록되었고 다시 적용할 수 있기 때문에 최종 커밋 단계에서 중단을 복구할 수 있습니다.

XNUMX단계 커밋은 단일 인스턴스 데이터베이스와 관련이 없지만 데이터가 여러 데이터베이스 인스턴스에 복제될 때 관련이 있습니다.

논리적 복제에서 XNUMX단계 커밋을 지원하는 것은 매우 중요합니다.

기능 개요

PG14 버전 이전에는 트랜잭션이 커밋된 후에만 논리적 복제 트랜잭션이 디코딩되고 복제되었습니다. 이는 복제 트랜잭션이 결국 중단되는 것을 방지하기 위한 것입니다.

커밋 시 트랜잭션 디코딩

PG14의 논리적 복제는 PREPARE TRANSACTION, COMMIT PREPARED 및 ROOLBACK PREPARED 명령을 지원합니다. PREPARE TRANSACTION 명령이 디코딩되면 트랜잭션이 디코딩되고 복사됩니다. PREPARE TRANSACTION은 WAL SENDER의 COMMIT처럼 트랜잭션 재생 및 디코딩을 시작합니다.

준비 중 트랜잭션 디코딩

또한 논리적 디코딩 플러그인이 XNUMX단계 제출을 지원할 수 있도록 새로운 플러그인 콜백을 정의했습니다.

콜백

설명

필터_준비_cb

플러그인이 PREPARE TRANSACTION 명령에 사용된 GID에 따라 준비할 때 디코딩할 필요가 없는 트랜잭션을 필터링하도록 허용합니다.

시작_준비_cb

트랜잭션 준비 시작

준비하다_cb

PREPARE TRANSACTION 명령이 디코딩될 때 호출됩니다.

커밋_준비_cb

COMMIT PREPARED 명령이 디코딩될 때 호출됩니다.

롤백_준비됨_cb

ROLLBACK PREPARED 명령이 디코딩될 때 호출됩니다.

플러그인 수정

테스트_디코딩

플러그인은 사용자가 자신의 논리적 디코딩 플러그인을 개발하는 데 도움이 되는 예로 논리적 디코딩 출력 플러그인입니다. test_decoding은 논리적 디코딩 메커니즘을 통해 WAL을 수신하고 수행된 작업의 텍스트 표현으로 디코딩합니다.

새로운 XNUMX단계 콜백 기능을 사용하고 준비하는 동안 트랜잭션을 디코딩할 수 있도록 수정되었습니다.

API 수정

pg_create_logical_replication_slot()

API는 슬롯이 XNUMX단계 커밋을 지원하는지 여부를 지정하는 새 옵션을 추가합니다. 출력 플러그인은 XNUMX단계 커밋을 지원하기 위해 XNUMX단계 옵션이 있는 복제 슬롯을 사용할 수 있습니다.

pg_create_logical_replication_slot(slot_name name, plugin name [, 임시 부울, XNUMX단계 부울 ] )

사례 연구

XNUMX단계 커밋 트랜잭션의 디코딩된 출력을 감지하는 방법을 살펴보겠습니다.

1) 복제 슬롯 생성

test_decoding을 출력 플러그인으로 사용하고 슬롯이 XNUMX단계 제출 및 디코딩을 지원하도록 true를 전달합니다.

postgres=# SELECT * FROM pg_create_logical_replication_slot('회귀_slot', 'test_decoding', false, true);

슬롯_이름 | lsn

------------------+-----------

회귀_slot | 0/16B1970

(1줄)

2) 테이블 생성

postgres=# CREATE TABLE 데이터(id 직렬 기본 키, 데이터 텍스트);

테이블 만들기

3) 트랜잭션 준비 및 커밋 트랜잭션의 디코딩된 출력 내용 감지

postgres = # BEGIN;

postgres=*# INSERT INTO data(data) VALUES('5');

postgres=*# PREPARE TRANSACTION '테스트_prepared1';

postgres=# SELECT * FROM pg_logical_slot_get_changes('회귀_slot', NULL, NULL);

lsn | xid | 데이터

-----------+------+-----------------

0/1689DC0 | 529 | 시작 529

0/1689DC0 | 529 | table public.data: INSERT: id[정수]:3 data[text]:'5'

0/1689FC0 | 529 | PREPARE TRANSACTION '테스트_prepared1', txid 529

(3열)

postgres=# COMMIT PREPARED 'test_prepared1';

postgres=# select * from pg_logical_slot_get_changes('회귀_slot', NULL, NULL);

lsn | xid | 데이터

-----------+------+------------------

0/168A060 | 529 | COMMIT PREPARED 'test_prepared1', txid 529

(4열)

postgres=# 데이터에서 * 선택;

아이디 | 데이터

────+─────

1 | 5

(1줄)

미래

이 기능에 대한 PG14의 변경 사항에는 준비 중 디코딩의 XNUMX단계 제출을 허용하는 디코더 측 인프라가 있습니다. 또한 이 인프라를 활용하기 위해 test_decoding 플러그인을 수정했습니다.

다음 단계는 PG에서 가장 큰 논리적 디코딩 플러그인인 pgoutput 플러그인에 대한 15단계 지원을 구현하는 것입니다. 이 플러그인은 논리적 복제의 PUBLISHER/SUBSCRIBER 모드를 지원합니다. 논리적 복제에서 가장 널리 사용되는 플러그인입니다. Fujitsu OSS 팀은 이 기능을 PGXNUMX에 추가하기 위해 오픈 소스 커뮤니티와 협력하고 있습니다.

분산 데이터베이스의 XNUMX단계 트랜잭션의 경우 PG는 다음을 지원해야 합니다. 대기 시스템은 호스트에 PREPARE가 실패했음을 알리고 롤백을 시작합니다. 이 피드백 메커니즘은 PG에서 지원되지 않으며 향후 개선 방향 중 하나입니다.

  모래밭:

6mbi25l-120

rm500uz-2h