0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

DynamoDB TransactionConflictExceptionのエラー対処

Posted at

エラー内容

TransactionConflictException: Transaction is ongoing for the item (DynamoDB)

ユーザーの操作が約10回に1回の頻度で失敗し、このDynamoDBのエラーが発生していました。

原因

公式ドキュメント(Botocore) で、以下のような説明がありました。

A transactional conflict can occur during concurrent item-level requests on an item within a transaction. Transaction conflicts can occur in the following scenarios:
(トランザクション競合は、トランザクション内の項目に対する項目レベルの同時リクエスト中に発生する場合があります。トランザクション競合は、次のシナリオで発生する場合があります。)

つまり「同じアイテムに対して、同時にトランザクション処理が実行されるとバッティングしてエラーが発生する」ということでした。

実際にフロントエンド側で以下のように Promise.all によって2つのトランザクションを同時に実行していました。

await Promise.all([
  updateItemTransaction1({ 
    body: {
        itemId: itemId
    }
  }),
  updateItemTransaction2({
    body: {
        itemId: itemId
    }
  }),
])

このため、非同期で実行される2つの処理が、たまたま同じタイミングでDynamoDBの同じアイテムを更新しようとして、バッティングが発生していました。
そのため、毎回エラーになるわけではなく、発生頻度が低かったのはこのタイミングの問題です。

対応

以下のように、2つの処理を順番に実行するよう変更することで、トランザクションの競合を回避できました。

await updateItemTransaction1({ 
    body: {
        itemId: itemId
    }
})
await updateItemTransaction2({
    body: {
        itemId: itemId
    }
}),

逐次実行にすることで、トランザクションが競合することなく安定して処理が完了するようになりました。

補足

リトライ処理を検討してもよいかもしれません。
TransactionConflictException は一時的なエラーのため、一定の間隔で再試行すれば成功することもあるようです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?