Amazon DynamoDB Transactions: 仕組み - Amazon DynamoDB

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

Amazon DynamoDB Transactions: 仕組み

Amazon DynamoDB トランザクションでは、複数のアクションをグループ化し、単一の all-or-nothing TransactWriteItems または TransactGetItemsオペレーションとして送信できます。以下のセクションでは、API オペレーション、容量管理、ベストプラクティス、DynamoDB でのトランザクション操作の使用に関する他の詳細について説明します。

TransactWriteItems API

TransactWriteItems は、1 回のオペレーションで最大 100 の書き込みアクションをグループ化する同期的でべき等な書き込み all-or-nothing オペレーションです。これらのアクションは、同じ AWS アカウントおよび同じリージョン内の 1 つ以上の DynamoDB テーブルにある最大 100 個の異なる項目をターゲットにすることができます。トランザクション内のアイテムの合計サイズは 4 MB を超えることはできません。すべて成功するかどれも成功しないかのどちらとなるように、アトミックに実行されます。

注記
  • TransactWriteItems オペレーションは、含まれるすべてのアクションを正常に完了する必要があり、そうでない場合は変更がまったく行われないという点で BatchWriteItem オペレーションとは異なります。BatchWriteItem オペレーションでは、バッチ内の一部のアクションのみ成功し、他のアクションは成功しないことがあり得ます。

  • インデックスを使用してトランザクションを実行することはできません。

同じトランザクション内の複数のオペレーションが同じ項目をターゲットとすることはできません。たとえば、同じトランザクション内で同じ項目に対して ConditionCheck を実行し、Update アクションも実行することはできません。

以下のタイプのアクションをトランザクションに追加できます。

  • Put — PutItem オペレーションを開始し、条件付きで、または条件をまったく指定せずに、新しい項目を作成するか、古い項目を新しい項目に置き換えます。

  • Update — UpdateItem オペレーションを開始し、既存の項目の属性を編集するか、まだ存在しない場合は新しい項目をテーブルに追加します。条件付きまたは条件なしで既存の項目で属性を追加、削除、更新するには、このアクションを使用します。

  • Delete — DeleteItem オペレーションを開始し、プライマリキーにより識別される 1 つの項目をテーブルで削除します。

  • ConditionCheck — 項目が存在することを確認するか、項目の特定の属性の条件を確認します。

トランザクションが完了すると、そのトランザクションによって加えられた変更は、グローバルセカンダリインデックス (GSI)、ストリーム、バックアップに反映されます。伝播は即時または即時ではないため、テーブルがバックアップ (RestoreTableFromBackup) から復元されるか、伝播中にポイントインタイム (ExportTableToPointInTime) にエクスポートされた場合、最近のトランザクション中に行われた変更の一部のみが含まれる可能性があります。

冪等性

TransactWriteItems 呼び出しを行ってリクエストが冪等であることを確認する場合、オプションでクライアントトークンを含めることができます。トランザクションを冪等にすると、接続のタイムアウトや他の接続問題に伴って同じオペレーションが複数回送信された場合に、アプリケーションエラーを防ぐことができます。

元の TransactWriteItems 呼び出しが成功した場合、同じクライアントトークンを持つ以降の TransactWriteItems 呼び出しは変更なしで正常に返ります。ReturnConsumedCapacity パラメータが設定されている場合、最初の TransactWriteItems 呼び出しは変更時に消費された書き込みキャパシティーユニットの数を返します。同じクライアントトークンを持つ以降の TransactWriteItems 呼び出しは、項目の読み取り時に消費された読み取りキャパシティユニットの数を返します。

冪等性について重要な点
  • クライアントトークンは、それを使用するリクエストが完了してから 10 分間有効です。10 分後、同じクライアントトークンを使用するリクエストは新しいリクエストとして扱われます。10 分が経過してから、同じリクエストに同じクライアントトークンを再利用しないでください。

  • 10 分間のべき等性期間内に同じクライアントトークンを使用してリクエストを繰り返すとき、他の一部のリクエストパラメータを変更した場合、DynamoDB は IdempotentParameterMismatch 例外を返します。

書き込みのエラー処理

以下の条件下では、書き込みトランザクションが成功しません。

  • いずれかの条件式の条件が満たされていない場合。

  • 同じ TransactWriteItems オペレーション内の複数のアクションが同じ項目をターゲットとしているために、トランザクション検証エラーが発生した場合。

  • TransactWriteItems リクエストが、TransactWriteItems リクエスト内の 1 つ以上の項目に対する継続中の TransactWriteItems オペレーションと競合する場合。この場合、リクエストは TransactionCanceledException で失敗します。

  • トランザクションを完了するプロビジョンドキャパシティーが足りない場合。

  • 項目サイズが大きくなりすぎる (400 KB 超)、ローカルセカンダリインデックス (LSI) が大きくなりすぎる、またはトランザクションにより変更が加えられたために同様の検証エラーが発生した場合。

  • 無効なデータ形式などのユーザーエラーがある場合。

TransactWriteItems オペレーションとの競合がどのように処理されるかについて詳しくは、「DynamoDB でのトランザクション競合の処理」を参照してください。

TransactGetItems API

TransactGetItems は、最大 100 個の Get アクションをまとめてグループ化する同期読み取りオペレーションです。これらのアクションは、同じ AWS アカウントおよびリージョン内の 1 つ以上の DynamoDB テーブルにある最大 100 個の異なる項目をターゲットにすることができます。トランザクション内の項目の合計サイズは 4 MB を超えることはできません。

Get アクションは、すべて成功するかすべて失敗するかのどちらとなるように、アトミックに実行されます。

  • Get — GetItem オペレーションを開始し、指定されたプライマリキーを持つ項目の属性のセットを取得します。一致する項目が見つからない場合、Get はデータを返しません。

読み込みのエラー処理

以下の条件下では、読み取りトランザクションが成功しません。

  • TransactGetItems リクエストが、TransactWriteItems リクエスト内の 1 つ以上の項目に対する継続中の TransactGetItems オペレーションと競合する場合。この場合、リクエストは TransactionCanceledException で失敗します。

  • トランザクションを完了するプロビジョンドキャパシティーが足りない場合。

  • 無効なデータ形式などのユーザーエラーがある場合。

TransactGetItems オペレーションとの競合がどのように処理されるかについて詳しくは、「DynamoDB でのトランザクション競合の処理」を参照してください。

DynamoDB トランザクションの分離レベル

トランザクションオペレーション (TransactWriteItems または TransactGetItems) と他のオペレーションの分離レベルは、次のとおりです。

SERIALIZABLE

直列化可能分離レベルでは、複数の同時オペレーションの結果は、前のオペレーションが完了するまでオペレーションが開始されない場合と同じになります。

以下のタイプのオペレーション間には、直列化可能分離があります。

  • トランザクションオペレーションと標準書き込みオペレーション (PutItemUpdateItem、または DeleteItem) の間。

  • トランザクションオペレーションと標準読み取りオペレーション (GetItem) の間。

  • TransactWriteItems オペレーションと TransactGetItems オペレーションの間。

トランザクションオペレーションとオペレーション内の個々の標準書き込みの間には直列化可能な分離がありますがBatchWriteItem、トランザクションとユニットとしてのBatchWriteItemオペレーションの間に直列化可能な分離はありません。

同様に、トランザクションオペレーションと GetItems オペレーションの個別の BatchGetItem 間の分離レベルは直列化可能です。ただし、トランザクションとユニットとしての BatchGetItem オペレーション間の分離レベルはコミット済み読み取りです。

単一の GetItem リクエストは、TransactWriteItems リクエストの前または後に行う 2 つの方法のいずれかで、TransactWriteItems リクエストに関してシリアル化することができます。同時実行 TransactWriteItems リクエストのキーに対する複数の GetItem リクエストは、任意の順序で実行できるため、結果は読み込みがコミットされます。

たとえば、項目 A と項目 B の GetItem リクエストが、項目 A と項目 B の両方を変更する TransactWriteItems リクエストと同時に実行される場合、次の 4 つの可能性があります。

  • 両方の GetItem リクエストは、TransactWriteItems リクエストの前に実行されます。

  • 両方の GetItem リクエストは、TransactWriteItems リクエストの後に実行されます。

  • 項目 A の GetItem リクエストは、TransactWriteItems リクエストの前に実行されます。項目 B の場合、GetItemTransactWriteItems の後に実行されます。

  • 項目 B の GetItem リクエストは、TransactWriteItems リクエストの前に実行されます。項目 A の場合、GetItemTransactWriteItems の後に実行されます。

複数のGetItemリクエストに対して直列化可能な分離レベルTransactGetItemsを希望する場合は、 を使用する必要があります。

処理中の同じトランザクション書き込みリクエストの一部であった複数の項目に対してトランザクション以外の読み取りが行われた場合、一部の項目と他の項目の古い状態の新しい状態を読み取ることができる可能性があります。トランザクション書き込みリクエストに含まれていたすべての項目の新しい状態は、トランザクション書き込みの正常な応答が受信された場合にのみ読み取ることができます。

コミット済み読み取り

コミット済み読み取り分離により、読み取りオペレーションは常に項目のコミット済み値を返します。つまり、読み取りによって、最終的に成功しなかったトランザクション書き込みの状態を表すビューが項目に表示されることはありません。コミット済み読み取り分離では、読み取りオペレーションの直後に項目の変更が防止されません。

分離レベルは、トランザクションオペレーションと、複数の標準読み取り (BatchGetItemQuery、または Scan) が関係する読み取りオペレーションの間ではコミット済み読み取りです。トランザクション書き込みにより BatchGetItemQuery、または Scan オペレーションの途中で項目が更新された場合、その後の読み取りオペレーションの部分では、新しくコミットされた値 (ConsistentRead) を使用) か、場合によってはそれ以前のコミット済み値 (結果整合性のある読み込み) を返します。

オペレーションの概要

以下の表は、トランザクションオペレーション (TransactWriteItems または TransactGetItems) と他のオペレーションの間の分離レベルをまとめたものです。

オペレーション 分離レベル

DeleteItem

直列化可能

PutItem

直列化可能

UpdateItem

直列化可能

GetItem

直列化可能

BatchGetItem

コミット済み読み取り*

BatchWriteItem

直列化不可*

Query

コミット済み読み取り

Scan

コミット済み読み取り

他のトランザクションオペレーション

直列化可能

アスタリスク (*) が付いたレベルは、ユニットとしてオペレーションに適用されます。ただし、これらのオペレーション内の個々のアクションの分離レベルは直列化可能です。

DynamoDB でのトランザクション競合の処理

トランザクション競合は、トランザクション内の項目に対する項目レベルの同時リクエスト中に発生する場合があります。トランザクション競合は、次のシナリオで発生する場合があります。

  • 項目に対する PutItemUpdateItem、または DeleteItem リクエストが、同じ項目を含む継続中の TransactWriteItems リクエストと競合する。

  • TransactWriteItems リクエスト内の項目が、継続中の別の TransactWriteItems リクエストの一部である。

  • TransactGetItems リクエスト内の項目が、継続中の TransactWriteItemsBatchWriteItemPutItemUpdateItem、または DeleteItem リクエストの一部である。

注記
  • PutItemUpdateItem、または DeleteItem リクエストが拒否された場合、リクエストは TransactionConflictException で失敗します。

  • TransactWriteItems または TransactGetItems 内の項目レベルのリクエストが拒否された場合、リクエストは TransactionCanceledException で失敗します。そのリクエストが失敗した場合、AWS SDK はリクエストを再試行しません。

    を使用している場合AWS SDK for Java、例外には のリストが含まれCancellationReasonsTransactItemsリクエストパラメータの項目のリストに従って順序付けられます。他の言語の場合、リストの文字列表現が例外のエラーメッセージに含まれます。

  • 継続中の TransactWriteItems オペレーションまたは TransactGetItems オペレーションが同時 GetItem リクエストと競合している場合、両方のオペレーションが成功する可能性があります。

TransactionConflict CloudWatch メトリクスは、失敗した項目レベルのリクエストごとに増分されます。

DynamoDB アクセラレーター (DAX) でのトランザクション API の使用

TransactWriteItemsTransactGetItems が、どちらも DynamoDB と同じ分離レベルで DynamoDB アクセラレーター (DAX) でサポートされています。

TransactWriteItems は DAX を介して書き込みます。DAX は DynamoDB に TransactWriteItems コールを渡し、応答を返します。書き込み後にキャッシュにデータを追加するために、DAX は、TransactWriteItems オペレーション内の各項目に対してバックグラウンドで TransactGetItems をコールします。これにより、追加の読み込み容量単位が消費されます。(詳しくは、トランザクションの容量管理 を参照してください)。この機能により、アプリケーションロジックをシンプルに保ち、トランザクション処理と非トランザクション処理の両方に DAX を使用できます。

TransactGetItems コールは、項目がローカルにキャッシュされることなく DAX を通過します。これは、DAX の強い整合性のある読み込み API と同じです。

トランザクションの容量管理

DynamoDB テーブルのトランザクションを有効にするために、追加コストはかかりません。料金の支払いは、トランザクションの一部である読み込みまたは書き込みに対してのみ行われます。DynamoDB は、トランザクション内の各項目の基になっている 2 つの読み込みまたは書き込みを実行します。1 つはトランザクションの準備用で、もう 1 つはトランザクションのコミット用です。基になる 2 つの読み取り/書き込みオペレーションが Amazon CloudWatch メトリクスに表示されます。

容量をテーブルにプロビジョニングするとき、トランザクション API により要求される追加の読み取りと書き込みを計画してください。たとえば、アプリケーションが 1 秒あたり 1 件のトランザクションを実行し、各トランザクションは 500 バイトの項目を 3 個テーブルに書き込むとします。各項目には、2 つの書き込みキャパシティーユニット (WCU) が必要です。1 つはトランザクションの準備用で、もう 1 つはトランザクションのコミット用です。したがって、テーブルには WCU を 6 個プロビジョニングする必要があります。

前の例で DynamoDB アクセラレーター (DAX) を使用していた場合、TransactWriteItems のコールで項目ごとに 2 つの読み込み容量単位 (RCU) も使用します。したがって、テーブルには追加の RCU を 6 個プロビジョニングする必要があります。

同様に、アプリケーションが 1 秒あたり 1 件の読み込みトランザクションを実行し、各トランザクションは 500 バイトの項目を 3 個テーブルで読み取る場合、読み込み容量単位 (RCU) を 6 個テーブルにプロビジョンする必要があります。各項目を読み取るには、2 つの RCU が必要です。1 つはトランザクションの準備用で、もう 1 つはトランザクションのコミット用です。

さらに、SDK のデフォルトの動作は、TransactionInProgressException 例外が発生した場合にトランザクションを再試行します。これらの再試行で消費される追加の読み込みキャパシティーユニット (RCU) を計画してください。同じことは、ClientRequestToken を使用して独自のコードでトランザクションを再試行しようとする場合に当てはまります。

トランザクションのベストプラクティス

DynamoDB トランザクションの使用時に推奨される以下の手法を検討してください。

  • テーブルで自動スケーリングを有効にするか、トランザクションの項目ごとに 2 つの読み取りまたは書き込みオペレーションを実行するのに十分なスループット容量をプロビジョニングしたことを確認します。

  • AWS によって提供された SDK を使用していない場合、TransactWriteItems 呼び出しを行うときに ClientRequestToken 属性を含め、リクエストがべき等となるようにします。

  • 必要でない場合は、トランザクションにオペレーションをまとめてグループ化しないでください。たとえば、10 個のオペレーションを持つ 1 つのトランザクションを、アプリケーションの正確性を低下させずに複数のトランザクションに分割できる場合、トランザクションを分割することをお勧めします。トランザクションをシンプルにするとスループットが向上し、成功する可能性が高まります。

  • 同じ項目を同時に更新する複数のトランザクションによって、トランザクションをキャンセルする競合が発生する可能性があります。そのような競合を最小限に抑えるため、データモデリングには以下の DynamoDB のベストプラクティスをお勧めします。

  • 属性のセットが 1 つのトランザクションの一部として複数の項目間で頻繁に更新される場合、属性を 1 つの項目にグループ化し、トランザクションのスコープを減らすことを検討してください。

  • データを大量に取り込むためにトランザクションを使用しないでください。一括書き込みには、BatchWriteItem の使用をお勧めします。

グローバルテーブルでのトランザクション API の使用

DynamoDB トランザクションに含まれるオペレーションは、トランザクションが最初に実行されたリージョンでのみトランザクションであることが保証されます。トランザクション内で適用された変更がリージョン間でグローバルテーブルレプリカにレプリケートされても、トランザクションは保持されません。

DynamoDB トランザクションと AWSLabs トランザクションクライアントライブラリ

DynamoDB トランザクションは、AWSLabsトランザクションクライアントライブラリのコスト効率、堅牢性、パフォーマンスに優れた置き換えを提供します。ネイティブのサーバー側トランザクション API を使用するようにアプリケーションを更新することをお勧めします。