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 レコードには 1 つの 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
前に and 後に 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. |
前に |
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. |
後に |
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 前に image, the 後に image, or both.
Aurora DSQL omits the chunked image from the top-level 前に or
後に 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 が 9 MiB を超えると、Aurora DSQL は before および/または after イメージを分割し、複数の Kinesis レコードを配信します。各レコードには、その構造を示す最上位の type フィールドが含まれています。完全なレコードの場合は full、フラグメントを参照するメインレコードの場合は chunked、チャンクイメージの個々の部分の場合は fragment です。チャンク化されたメインレコードの 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 チェックサム) があります。1 つのイメージがインラインで、もう 1 つのイメージがチャンク化されている場合、インラインイメージは依然として最上位レベルに値または 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 に設定され、3 つのフィールドを持つ独自の Kinesis レコードです。chunk_id は、メインレコードの対応する chunked.before.chunk_id または chunked.after.chunk_id の値と一致し、index はイメージ内のフラグメントのゼロベースの位置であり、data は UTF-8 文字境界で分割されたイメージの JSON テキストのセグメントです (各フラグメントの data 値は、それ自体が有効な UTF-8 文字列です)。Aurora DSQL CDC は UNORDERED モードとランダム化されたパーティションキーを使用するため、フラグメントとメインレコードは異なるシャードに任意の順序で到着する可能性があります。すべてのフラグメントを読み取るには、Kinesis データストリーム上のすべてのシャードを消費します。配信の順序付けの詳細については、「順序付け」を参照してください。
{ "type": "fragment", "chunk_id": "chunk-id", "index": 0, "data": "partial-JSON-text" }
サイズの大きいイメージを再構成するには、type が fragment の各レコードを chunk_id でバッファします。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 (int2) |
JSON number | 42 |
integer (int4) |
JSON number | 1001 |
bigint (int8) |
JSON number | 9223372036854775807 |
oid |
JSON number (unsigned) | 16384 |
JavaScript 環境では、bigint の値が ±2^53 を超えると精度が低下する可能性があります。このような場合は、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 表現 | 例 |
|---|---|---|
boolean |
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 表現 | 例 | 注意事項 |
|---|---|---|---|
date |
JSON number (days since Unix epoch) | 19,797 |
+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. |
interval |
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 エンベロープ形式を識別します。