2024-04-18,   조평연

본 포스팅은 CDC plugin 중 하나인 pgoutput 포멧을 알아보는 내용입니다.

1. pgoutput 이란?

  • postgresql 에서 논리적 복제를 위해 plugin을 설정하게 되는데 이때 기본이 되는 값입니다.
  • 성능을 위해 바이트 형태로 꼭 필요한 정보로 축약해서 나타냅니다.
  • 테스트를 용이하게 하기 위해 test_decoding plugin을 사용하면 사람이 보기 편하게 텍스트 형식으로 나옵니다.

2. pgoutput 을 사용하는 이유

  • 기존 test_decoding과 가장 큰 차이점은 전체 테이블을 보느냐 특정 테이블만을 바라보느냐 입니다.
  • test_decoding의 경우 전체 테이블의 정보를 읽고 pgoutput의 경우 설정을 통해 특정 테이블만을 볼 수 있습니다.
  • 해당 포스팅은 pgoutput의 포멧을 알아보는것에 집중하여 특정 테이블 설정 방법은 추후 다른 포스팅에서 다루겠습니다.

3. pgoutput 포멧

  • 순서는 Begin -> Insert, Update, Delete -> Commit 순이고 Insert 앞에는 Relation 이라는게 나와서 스키마, 테이블명, 컬럼명 등을 알려줍니다.

Begin

[ B (byte1) ] [ FinalLSN(int64) ] [ CommitTime(int64) ] [ TransactionId(int32) ]

  • B (byte1) : 버퍼의 시작을 ‘B’ 라는 단어로 식별
  • FinalLSN (Int64) : 트랜잭션 최종 LSN 정보
  • CommitTime (Int64) : 트랜잭션 타임스탬프 값, 값은 Postgresql epoch (2000-01-01) 이후의 마이크로 초 단위
  • TransactionId (Int32) : 트랜잭션 식별값(xid)

Relation

[ R(byte1) ] [ RelationOid(int32) ] [ SchemaName(String) ] [ TableName(String) ] [ ReplicaIdentity(int8) ] [ NumberOfColumns(int16) ] [ ColumnName(String) ] [ ColumnTypeOid(int32) ] [ Atttypmod(int32) ]

ColumnName(String) 부터 Atttypmod(int32) 까지는 컬럼의 수 만큼 반복됩니다.

  • R (byte1) : 버퍼의 시작을 ‘R’ 이라는 단어로 식별
  • RelationOid (Int32) : 테이블 객체 식별값 (Oid)
  • SchemaName (String) : 스키마 값
  • TableName (String) : 테이블 이름 값
  • ReplicaIdentity (Int8) : 테이블에 대한 복제본 Id 설정(pg_class의 relreplident와 동일)
  • NumberOfColumns (Int16) : 컬럼 총 개수
  • ColumnName (String) : 컬럼 이름
  • ColumnTypeOid (Int32) : 컬럼 타입 식별값
  • Atttypmod (Int32) : 컬럼 수정자

Insert

[ I(byte1) ] [ RelationOid(int32) ] [ IsNew(byte1) ] [ TupleData ]

Insert, Update, Delete에 공통으로 들어가는 TupleData 는 맨 마지막에 정리해놨습니다.

  • I (byte1) : 버퍼의 시작을 ‘I’ 라는 단어로 식별
  • RelationOid (Int32) : 테이블 객체 식별값 (Oid)
  • IsNew ‘N‘ (byte1) : 다음차례에 나올 TupleData 메시지를 새 튜플로 식별
  • TupleData : 새로운 튜플의 내용을 나타내는 부분 (Tuple 제목 참고)

Update

[ U(byte1) ] [ RelationOid(int32) ] [ keyOrTuple(byte1) ] [ TupleData ]

Insert, Update, Delete에 공통으로 들어가는 TupleData 는 맨 마지막에 정리해놨습니다.

  • U (byte1) : 버퍼의 시작을 ‘U’ 라는 단어로 식별
  • RelationOid (Int32) : 테이블 객체 식별값 (Oid)
  • keyOrTuple ‘K’ (byte1) : 업데이트로 인해 열의 데이터가 변경된 경우에 존재 REPLICA IDENTITY 인덱스의 일부
  • TupleData : 새로운 튜플의 내용을 나타내는 부분 (Tuple 제목 참고)

Delete

[ D(byte1) ] [ RelationOid(int32) ] [ keyOrTuple(byte1) ] [ TupleData ]

Insert, Update, Delete에 공통으로 들어가는 TupleData 는 맨 마지막에 정리해놨습니다.

  • D (byte1) : 버퍼의 시작을 ‘D’ 라는 단어로 식별
  • RelationOid (Int32) : 테이블 객체 식별값 (Oid)
  • keyOrTuple ‘K‘ or ‘O’ (byte1) :
    • byte1(‘K’) : 업데이트로 인해 열의 데이터가 변경된 경우에 존재 REPLICA IDENTITY 인덱스의 일부,
    • byte1(‘O’) : 메시지를 이전 튜플로 식별함 업데이트가 발생한 테이블의 REPLICA IDENTITY 가 FULL로 설정된 경우만 존재
  • TupleData : 새로운 튜플의 내용을 나타내는 부분 (Tuple 제목 참고)

Commit

[ C(byte1) ] [ CommitLSN(int64) ] [ EndLSN(int64) ] [ CommitTime(int64) ]

  • C (byte1) : 버퍼의 시작을 ‘C’ 라는 단어로 식별
  • CommitLSN (Int64) : 커밋 LSN 값
  • EndLSN (Int64) : 트랜잭션 끝 LSN 값
  • CommitTime (Int64) : 트랜잭션의 타임스탬프 커밋, 값은 postgresql epoch 이후의 마이크로초 단위

Tuple

[ NumberOfColumns(int16) ] [ n or u or t(byte1) ] [ StrLen(int32) ] [ Value(String) ]

n or u or t(byte1) 부터 Value(String) 까지는 컬럼의 수 만큼 반복됩니다.

  • NumberOfColumns (Int16) : 컬럼 총 개수
  • n or u or t (byte1) : 튜플 종류 식별
  • StrLen (Int32) : 튜플 값 총 길이
  • Value (String) : 튜플 값

4. 참고문헌

  • https://www.postgresql.org/docs/current/protocol-logicalrep-message-formats.html (postgresql 16버전 공식문서)

  • https://github.com/davecramer/LogicalDecode/blob/master/src/main/java/com/postgresintl/logicaldecoding/PgOutput.java (pgoutput 소스코드)

업데이트: