Amazon DynamoDB
開発者ガイド (API バージョン 2012-08-10)

Amazon DynamoDB トランザクション: 仕組み

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

TransactWriteItems API

TransactWriteItems は、同期的なべき等書き込みオペレーションであり、最大 10 の書き込みアクションを 1 つのオールオアナッシングオペレーションにグループ化します。これらのアクションは、同じ AWS アカウントおよび同じリージョン内の 1 つ以上の DynamoDB テーブルにある最大 10 個の異なる項目をターゲットとします。すべて成功するかどれも成功しないかのどちらとなるように、アトミックに実行されます。

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

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

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

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

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

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

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

トランザクションによって加えられた変更は、トランザクションが正常に完了した後、最終的にグローバルセカンダリインデックス (GSI)、DynamoDB ストリーム、バックアップに反映されます。結果整合性のため、オンデマンドまたはポイントインタイムリカバリ (PITR) バックアップから復元されたテーブルには、最近のトランザクションにより加えられた変更の一部 (すべてではなく) が含まれる可能性があります。

べき等性

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

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

べき等性について重要な点

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

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

書き込みのエラー処理

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

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

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

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

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

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

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

実行中の TransactWriteItems オペレーションが、TransactWriteItems オペレーション内の 1 つ以上の項目で同時 PutItemUpdateItemDeleteItem、または TransactGetItems リクエストと競合している場合、同時リクエストは TransactionCanceledException で失敗します。

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

TransactGetItems API

TransactGetItems は、最大 10 個の Get アクションをまとめてグループ化する同期読み取りオペレーションです。これらのアクションは、同じ AWS アカウントおよびリージョン内の 1 つ以上の DynamoDB テーブルにある最大 10 個の異なる項目をターゲットとします。

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

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

読み取りのエラー処理

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

  • 同時 PutItemUpdateItemDeleteItem、または TransactWriteItems リクエストと競合している継続的な TransactGetItems オペレーションがある場合。この場合、TransactGetItems オペレーションは TransactionCanceledException で失敗します。

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

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

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

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

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

SERIALIZABLE

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

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

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

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

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

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

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

コミット済み読み取り

コミット済み読み取り分離では、読み取りオペレーションが常に項目のコミット済み値を返します。コミット済み読み取り分離では、読み取りオペレーションの直後に項目の変更が防止されません。

分離レベルは、トランザクションオペレーションと、複数の標準読み取り (BatchGetItemQuery、または Scan) が関係する読み取りオペレーションの間ではコミット済み読み取りです。トランザクション書き込みにより BatchGetItemQuery、または Scan オペレーションの途中で項目が更新された場合、読み取りオペレーションは新しいコミット済み値を返します。

概要表

以下の表は、トランザクションオペレーション (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 for Java を使用している場合、例外には、TransactItems リクエストパラメータの項目リストに従って整理された CancellationReasons のリストが含まれます。他の言語の場合、リストの文字列表現が例外のエラーメッセージに含まれます。

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

DynamoDB Accelerator (DAX) でトランザクション API を使用する

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

TransactWriteItems は DAX を経由して書き込みます。DAX は TransactWriteItems コールをDynamoDB 渡して、レスポンスを返します。書き込み後にキャッシュにデータを追加するために、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 Accelerator (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 の使用

グローバルテーブルでは、トランザクションオペレーションがデフォルトで無効になります。グローバルテーブルでトランザクションを有効にする場合は、AWS サポートにお問い合わせください。

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

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