CDC 레코드 이해
중요
이 기능은 AWS 프리뷰로 제공되며 변경될 수 있습니다. 자세한 내용은 AWS 서비스 약관
정식 출시 전에 스트림 페이로드에 새 작업 유형(업데이트를 위한 "op": "u")을 추가합니다. 애플리케이션이 이러한 변경 사항을 수정하지 않고 처리하도록 하려면 after 페이로드를 적용하여 인식할 수 없는 op 값을 업서트로 취급합니다. 세부 정보는 CDC 레코드 이해 섹션을 참조하세요.
Aurora DSQL CDC는 각 변경 사항을 JSON 레코드로 전달합니다. 레코드는 작업 유형, 행 이미지 전후 및 소스 메타데이터가 있는 봉투 구조를 사용합니다.
레코드가 Amazon Kinesis에 매핑되는 방법
Aurora DSQL은 각 CDC 레코드를 단일 Kinesis 레코드로 기록합니다. Kinesis 레코드의 Data 필드에는 JSON 페이로드가 포함됩니다. Aurora DSQL은 무작위 Kinesis 파티션 키를 사용하여 CDC 레코드를 샤드에 균등하게 분산합니다. 모든 변경 사항을 읽으려면 Kinesis 데이터 스트림의 모든 샤드를 사용합니다. 레코드가 Kinesis 레코드 크기 제한을 초과하면 Aurora DSQL은 이를 여러 Kinesis 레코드로 분할합니다. 자세한 내용은 크기 초과 레코드 처리을 참조하세요.
참고
Kinesis 레코드에는 Data blob이 하나 있습니다. 프라이머리 키 값은 삭제를 위한 JSON 페이로드의 before 필드 또는 삽입 및 업데이트를 위한 after 필드에 표시됩니다. 다운스트림 처리를 위해 프라이머리 키를 추출하려면 페이로드의 해당 필드에서 읽습니다.
페이로드의 프라이머리 키
프라이머리 키가 있는 테이블의 경우 프라이머리 키 열 값이 페이로드에 나타납니다.
-
삽입 및 업데이트의 경우 페이로드에는
after필드의 다른 모든 열과 함께 프라이머리 키 열이 포함됩니다. -
삭제의 경우 프라이머리 키 열이
before필드에 나타납니다.
복합 프라이머리 키가 하나만 있는 테이블을 예로 들어 보겠습니다.
CREATE TABLE order_items ( order_id INT, item_id INT, quantity INT, price NUMERIC, PRIMARY KEY (order_id, item_id) );
이 테이블에서 삭제하면 "before": {"order_id": 1001, "item_id": 42}인 페이로드가 생성됩니다.
레코드 페이로드
페이로드는 다음 JSON 봉투 형식을 사용합니다.
INSERT 예
다음 예제에서는 삽입 작업에 대한 CDC 레코드를 보여줍니다.
{ "type": "full", "op": "c", "before": null, "after": {"order_id": 1001, "item_id": 42, "quantity": 5, "price": "29.99"}, "source": { "version": "1.0", "ts_ms": 1705318200000, "ts_ns": 1705318200000000000, "txId": "ffthunp5stx6ffs2vyfqoatmfu", "schema": "public", "table": "order_items", "db": "postgres", "cluster": "kmabugltfmjdaj2siqr2qbxgju" }, "ts_ms": 1705318200125, "ts_ns": 1705318200125483291 }
UPDATE 예제
다음 예제는 Aurora DSQL이 op: "u"를 내보내기 시작한 후 UPDATE 문에서 생성된 CDC 레코드가 어떻게 보이는지 보여줍니다.
중요
현재 Aurora DSQL은 삽입 및 업데이트 모두에 대해 op: "c"를 내보냅니다. 후속 릴리스는 업데이트에 대해 op: "u", 삽입에 대해 op: "c"를 내보냅니다. 소비자가 전환 과정에서 계속 작업할 수 있도록 c, u 및 d를 처리하도록 앱을 설계합니다.
{ "type": "full", "op": "u", "before": null, "after": {"order_id": 1001, "item_id": 42, "quantity": 10, "price": "29.99"}, "source": { "version": "1.0", "ts_ms": 1705318300000, "ts_ns": 1705318300000000000, "txId": "qvtiesgmd55cvlfukm3dfuotji", "schema": "public", "table": "order_items", "db": "postgres", "cluster": "kmabugltfmjdaj2siqr2qbxgju" }, "ts_ms": 1705318300125, "ts_ns": 1705318300125483291 }
DELETE 예제
프라이머리 키가 있는 테이블에 대한 삭제의 경우 before 필드에는 삭제된 행의 프라이머리 키 값이 포함됩니다.
{ "type": "full", "op": "d", "before": {"order_id": 1001, "item_id": 42}, "after": null, "source": { "version": "1.0", "ts_ms": 1705318400000, "ts_ns": 1705318400000000000, "txId": "xyzabc123def456ghi789jklmno", "schema": "public", "table": "order_items", "db": "postgres", "cluster": "kmabugltfmjdaj2siqr2qbxgju" }, "ts_ms": 1705318400125, "ts_ns": 1705318400125483291 }
페이로드 필드
| 필드 | 설명 |
|---|---|
형식 |
The record type. 전체 for a complete record that includes inline
before and after values. chunked for a main
record that references fragment records for one or both images. fragment
for an individual piece of a chunked image. For details, see
크기 초과 레코드 처리. |
op |
Operation type. c = create (insert), u = update,
d = delete. Currently Aurora DSQL emits c for both inserts and
updates. A subsequent release will emit u for updates, and
c for inserts. Design your app to handle all three values. |
before |
For deletes on tables with a primary key, contains the primary key values of the
deleted row. Aurora DSQL sets this field to null for inserts, updates, and
deletes on tables without a primary key. |
after |
The full row state after the change, including all columns. Aurora DSQL sets this field
to null for deletes. |
chunked |
Present only when 유형 is chunked. Contains reassembly
metadata for the before image, the after image, or both.
Aurora DSQL omits the chunked image from the top-level before or
after field and places it under chunked instead. For
details, see 크기 초과 레코드 처리. |
source.version |
The CDC source metadata format version. The current version is
1.0. |
source.ts_ms |
The transaction commit timestamp in milliseconds since the Unix epoch, Coordinated Universal Time (UTC). |
source.ts_ns |
Transaction commit timestamp in nanoseconds, UTC. The highest precision timestamp available. Use this field to establish a total order of transactions. |
source.txId |
A unique transaction identifier, encoded as base32. All records from the same
transaction share the same txId value. Use this field to group records
that belong to the same transaction. |
source.schema |
The PostgreSQL schema name (for example, 퍼블릭). |
source.table |
The table name. |
source.db |
The database name. Always postgres for Aurora DSQL. |
source.cluster |
The Aurora DSQL cluster identifier. |
ts_ms |
The time at which the CDC system processed the record, in milliseconds, UTC. The
difference between ts_ms and source.ts_ms is a measure of
replication lag. |
ts_ns |
The time at which the CDC system processed the record, in nanoseconds, UTC. |
형식 세부 정보
다음 세부 정보는 Aurora DSQL CDC가 레코드의 형식을 지정하는 방법을 설명합니다. 이러한 동작을 처리하도록 앱을 설계합니다.
-
삽입 및 업데이트를 위한 전체 사후 이미지. Aurora DSQL은 모든 쓰기에 대한
after필드에 전체 행 상태를 포함합니다.before필드는 삽입 및 업데이트에 대해null입니다. 현재 삽입과 업데이트 모두op: "c"를 사용하지만 후속 릴리스는 업데이트를 위해op: "u"를 내보냅니다. 삽입과 업데이트를 구분하기 위해op필드에 의존하지 않고 순서 지정에 프라이머리 키별source.ts_ns를 사용하도록 앱을 설계합니다. -
변경 후 행 상태만. CDC 레코드에는 각 변경 후 전체 행 상태가 포함됩니다. 업데이트 전 행의 상태는 포함되지 않습니다. 프라이머리 키가 있는 테이블에 대한 삭제의 경우
before필드에는 삭제된 행의 프라이머리 키 값이 포함됩니다. -
문자열로 직렬화된 숫자 유형. Aurora DSQL은 정확한 정밀도를 유지하기 위해
numeric및decimal값을 JSON 문자열로 직렬화합니다. -
Base64로 인코딩된 이진 데이터. Aurora DSQL은
bytea값을 Base64 문자열로 인코딩합니다. -
특수 부동 소수점 및 숫자 값. Aurora DSQL은 NaN 및 ±Infinity를 문자열
"NaN","Infinity"및"-Infinity"로 직렬화합니다. 이는real,double precision및numeric유형에 적용됩니다. -
JSON 문자열로 직렬화된 JSON 열. Aurora DSQL은
json열 값을 열에 저장된 원시 JSON 텍스트가 포함된 JSON 문자열로 직렬화합니다. 앱의 문자열 값(예: JavaScript의JSON.parse또는 Python의json.loads)을 구문 분석하여 기본 JSON 값에 액세스합니다. -
null로 내보낸 오버플로 값. 직렬화 중에 대상 JSON 유형에서 값을 표시할 수 없는 경우 Aurora DSQL은 해당 열에 대해 JSON
null을 내보냅니다. 이는 총 마이크로초가 부호 있는 64비트 정수 범위 ±9,223,372,036,854,775,807마이크로초, 약 ±292,271년)를 초과하는interval값에 적용됩니다. 데이터베이스 스키마에서 null이 불가능한 열의 예상치 못한null값을 처리하도록 앱을 설계합니다. -
크기가 큰 레코드는 청크로 분할됨. 레코드가 Amazon Kinesis 레코드 크기 제한을 초과하는 경우 Aurora DSQL은 영향을 받는
before또는after이미지를 조각으로 분할하고 별도의 Kinesis 레코드로 전송하므로 변경 사항을 계속 수신할 수 있습니다. 이미지를 재조립하도록 앱을 설계합니다. 자세한 내용은 크기 초과 레코드 처리을 참조하세요.
크기 초과 레코드 처리
CDC 레코드의 직렬화된 JSON이 9MiB를 초과하면 Aurora DSQL은 before 및/또는 after 이미지를 분할하여 여러 Kinesis 레코드를 전송합니다. 각 레코드에는 전체 레코드의 경우 full, 조각을 참조하는 기본 레코드의 경우 chunked, 청크 이미지의 개별 조각의 경우 fragment 등 구조를 나타내는 최상위 type 필드가 포함되어 있습니다. 청크된 기본 레코드의 op, source, ts_ms 및 ts_ns 필드는 전체 레코드와 동일하게 작동합니다. 단일 Kinesis 레코드에 맞는 레코드는 type이 full로 설정되며 추가 처리가 필요하지 않습니다.
chunk_id는 재시도 시 안정적입니다. Aurora DSQL이 조각을 재전송하는 경우 조각은 원래 전송과 동일한 chunk_id를 전달하므로 앱은 이전 시도의 부분 세트를 처리하지 않고도 동일한 식별자로 버퍼링을 계속할 수 있습니다.
기본 레코드
청크된 기본 레코드는 분할 이미지의 최상위 before 또는 after 필드를 재조립 방법을 설명하는 chunked 객체로 대체합니다. chunked의 각 항목에는 chunk_id(이 레코드에 조각을 연결하는 식별자), total_fragments(해당 이미지를 구성하는 조각 수) 및 crc32c(재조립된 이미지 텍스트 위에 10진수 문자열로 CRC32C 체크섬)가 있습니다. 한 이미지가 인라인이고 다른 이미지가 청크된 경우에도 인라인 이미지는 최상위 수준에 값 또는 null로 표시됩니다.
{ "type": "chunked", "op": "c", "before": null, "after": null, "source": { "version": "1.0", "ts_ms": 1705318200000, "ts_ns": 1705318200000000000, "txId": "ffthunp5stx6ffs2vyfqoatmfu", "schema": "public", "table": "order_items", "db": "postgres", "cluster": "cluster-id" }, "chunked": { "after": { "chunk_id": "chunk-id", "total_fragments": 3, "crc32c": "2073618257" } }, "ts_ms": 1705318200125, "ts_ns": 1705318200125483291 }
조각 레코드
각 조각은 type이 fragment로 설정되고 다음 세 개의 필드가 있는 자체 Kinesis 레코드입니다. chunk_id는 기본 레코드에 있는 해당 chunked.before.chunk_id 또는 chunked.after.chunk_id의 값과 일치하고, index는 이미지 내 조각의 0 기반 위치이며, data는 UTF-8 문자 경계에 분할된 이미지 JSON 텍스트의 세그먼트입니다(각 조각의 data 값은 자체적으로 유효한 UTF-8 문자열임). Aurora DSQL CDC는 UNORDERED 모드 및 무작위 파티션 키를 사용하기 때문에 조각과 기본 레코드는 어떤 순서로든 서로 다른 샤드에 도착할 수 있습니다. 모든 조각을 읽으려면 Kinesis 데이터 스트림의 모든 샤드를 사용합니다. 전송 순서 지정에 대한 자세한 내용은 순서 지정 섹션을 참조하세요.
{ "type": "fragment", "chunk_id": "chunk-id", "index": 0, "data": "partial-JSON-text" }
크기 초과 이미지를 재조립하려면 각 레코드를 chunk_id별로 type fragment로 버퍼링합니다. type chunked로 기본 레코드를 받으면 chunked.before 또는 chunked.after에서 참조되는 각 chunk_id에 대한 total_fragments 조각이 있을 때까지 기다렸다가 index 오름차순으로 조각을 정렬하고 data 문자열을 연결합니다. 연결된 결과는 원본 before 또는 after 객체를 JSON 텍스트로 구문 분석하여 열 값에 액세스합니다. 전송 무결성을 확인하려면 연결된 문자열을 통해 CRC32C를 계산하고 결과를 chunked.before.crc32c 또는 chunked.after.crc32c와 비교합니다.
데이터 유형 직렬화
다음 표에서는 Aurora DSQL이 CDC 레코드의 각 PostgreSQL 데이터 형식을 직렬화하는 방법을 설명합니다.
정수 형식
| PostgreSQL 데이터 형식 | JSON 표현 | 예제 |
|---|---|---|
smallint ("char") |
JSON number | 42 |
정수 ("char") |
JSON number | 1001 |
bigint ("char") |
JSON number | 9223372036854775807 |
oid |
JSON number (unsigned) | 16384 |
bigint 값이 ±2^53을 초과하면 JavaScript 환경에서 정밀도가 떨어질 수 있습니다. 이러한 경우 BigInt 또는 임의 정밀도 라이브러리를 사용합니다.
부동 소수점 형식
| PostgreSQL 데이터 형식 | JSON 표현 | 예제 | 참고 |
|---|---|---|---|
real (float4) |
JSON number | 3.14159 |
NaN and ±Infinity are serialized as the strings "NaN",
"Infinity", "-Infinity". |
double precision (float8) |
JSON number | 3.141592653589793 |
Same special value handling as real. |
numeric / decimal |
JSON string | "123.45" |
Always a string to preserve exact precision. NaN and ±Infinity are serialized
as the strings "NaN", "Infinity",
"-Infinity". |
부울
| PostgreSQL 데이터 형식 | JSON 표현 | 예제 |
|---|---|---|
부울 |
JSON boolean | true or false |
문자 형식
| PostgreSQL 데이터 형식 | JSON 표현 | 예제 |
|---|---|---|
varchar / 텍스트 |
JSON string | "Hello, world!" |
bpchar (char(n)) |
JSON string | "ABC" (trailing spaces stripped) |
이름 |
JSON string | "pg_class" |
"char" (single-byte) |
JSON string | "A" |
바이너리
| PostgreSQL 데이터 형식 | JSON 표현 | 예제 |
|---|---|---|
bytea |
JSON string (Base64) | "SGVsbG8gV29ybGQh" |
날짜 및 시간 형식
| PostgreSQL 데이터 형식 | JSON 표현 | 예제 | 참고 |
|---|---|---|---|
날짜 |
JSON number (days since Unix epoch) | 19797 |
+infinity and -infinity are represented as sentinel day
counts derived from epoch-offset arithmetic. These values don't correspond to
meaningful calendar dates. |
시간 |
JSON number (microseconds since midnight) | 52200123456 |
|
timetz |
JSON number (microseconds since midnight, UTC) | 52200123456 |
The local time is adjusted to UTC by applying the stored timezone offset (seconds west of UTC). The result is wrapped to the range [0, 86400000000) microseconds. |
timestamp |
JSON number (microseconds since Unix epoch) | 1710510600123456 |
±Infinity maps to sentinel values: 9223372036825200000
for +infinity and -9223372036832400000 for
-infinity. |
timestamptz |
JSON number (microseconds since Unix epoch) | 1710510600123456 |
Stored and emitted in UTC. Same ±infinity sentinel values as
timestamp. |
간격 |
JSON number (approximate total microseconds) | 2802603000000 |
Months are approximated as 30.4375 days (2,629,800 seconds). The total is
computed as (월 × 2,629,800 + 일 × 86,400) × 1,000,000 + 마이크로초. If the result exceeds the 64-bit signed integer
range (±9,223,372,036,854,775,807 microseconds, approximately
±292,271 years), Aurora DSQL emits JSON null for the column. |
기타 유형
| PostgreSQL 데이터 형식 | JSON 표현 | 예제 |
|---|---|---|
uuid |
JSON string (standard 8-4-4-4-12 hex format) | "550e8400-e29b-41d4-a716-446655440000" |
oidvector |
JSON empty array | [] |
json |
JSON string containing the raw JSON text | "{\"key\": \"value\"}" |
Null 값
모든 데이터 유형의 경우 NULL 열 값은 JSON null로 표시됩니다.
CDC 레코드의 스키마 진화
열 추가, 삭제 또는 이름 변경과 같이 테이블의 스키마를 수정하는 경우 CDC 레코드는 DDL 변경을 커밋한 트랜잭션부터 시작하여 변경 사항을 반영합니다. DDL 변경 전에 커밋된 트랜잭션의 레코드는 이전 스키마를 사용합니다. 예제:
-
열을 추가하면 이전 트랜잭션의 레코드에 새 열이 포함되지 않습니다. 트랜잭션 추가 이후 레코드에는 새 열이 포함됩니다.
-
열을 삭제하면 삭제 트랜잭션 이후 레코드에 더 이상 해당 열이 포함되지 않습니다.
-
열 이름을 바꾸면 이름 바꾸기 트랜잭션의 레코드가 새 열 이름을 사용합니다.
각 레코드의 after 및 before 필드에 있는 열 이름을 검사하여 다운스트림 소비자의 스키마 변경 사항을 추적합니다. 각 레코드의 source.version 필드는 CDC 봉투 형식을 식별합니다.