pgoutput
본 포스팅은 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 소스코드)