話題の記事

[速報]待望のDynamoDBのトランザクションがリリースされました! #reinvent

2018.11.28

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

先程、公式ブログにてDynamoDBのトランザクションがネイティブでサポートされた事が発表されました!!

DynamoDBトランザクションは、単一のAWSアカウントおよび領域内の複数のテーブルにわたって、原子性、一貫性、分離性、耐久性 (ACID)を提供します。 1つの論理的なビジネス操作の一部として、複数のアイテムに対するコーディネートされた挿入、削除、または更新を必要とするアプリケーションを構築するときに、 トランザクションを使用できます。DynamoDBは、複数のパーティションとテーブル間でトランザクションをサポートする唯一の非リレーショナルデータベースです。

新機能

  • TransactGetItems
  • TransactWriteItems

各ドキュメント

分離レベルはシリアライズ

分離レベルとは一括処理(トランザクション)が複数同時に行われた場合に、どれほどの一貫性・正確性で実行するかを4段階で定義したものです。

  • SERIALIZABLE ( 直列化可能 )
    • 複数の並行に動作するトランザクションそれぞれの結果が、いかなる場合でも、それらのトランザクションを時間的重なりなく逐次実行した場合と同じ結果となる。このような性質を直列化可能性(Serializability)と呼ぶ.SERIALIZABLEは最も強い分離レベルであり、最も安全にデータを操作できるが、相対的に性能は低い。ただし同じ結果とされる逐次実行の順はトランザクション処理のレベルでは保証されない。
  • REPEATABLE READ ( 読み取り対象のデータを常に読み取る )
    • ひとつのトランザクションが実行中の間、読み取り対象のデータが途中で他のトランザクションによって変更される心配はない。同じトランザクション中では同じデータは何度読み取りしても毎回同じ値を読むことができる。 ただし ファントム・リード(Phantom Read) と呼ばれる現象が発生する可能性がある。ファントム・リードでは、並行して動作する他のトランザクションが追加したり削除したデータが途中で見えてしまうため、処理の結果が変わってしまう。
  • READ COMMITTED ( 確定した最新データを常に読み取る )
    • 他のトランザクションによる更新については、常にコミット済みのデータのみを読み取る。 MVCC はREAD COMMITTEDを実現する実装の一つである。 ファントム・リード に加え、非再現リード(Non-Repeatable Read)と呼ばれる、同じトランザクション中でも同じデータを読み込むたびに値が変わってしまう現象が発生する可能性がある。
  • READ UNCOMMITTED ( 確定していないデータまで読み取る )
    • 他の処理によって行われている、書きかけのデータまで読み取る。PHANTOM 、 NON-REPEATABLE READ 、さらに ダーティ・リード(Dirty Read) と呼ばれる現象(不完全なデータや、計算途中のデータを読み取ってしまう動作)が発生する。トランザクションの並行動作によってデータを破壊する可能性は高いが、その分性能は高い。

DynamoDB Transactionsの分離レベルはserializableです。

JavaScriptSDKのサンプルコード(引用)

data = await dynamoDb.transactWriteItems({
    TransactItems: [
        {
            Update: {
                TableName: 'items',
                Key: { id: { S: itemId } },
                ConditionExpression: 'available = :true',
                UpdateExpression: 'set available = :false, ' +
                    'ownedBy = :player',
                ExpressionAttributeValues: {
                    ':true': { BOOL: true },
                    ':false': { BOOL: false },
                    ':player': { S: playerId }
                }
            }
        },
        {
            Update: {
                TableName: 'players',
                Key: { id: { S: playerId } },
                ConditionExpression: 'coins >= :price',
                UpdateExpression: 'set coins = coins - :price, ' +
                    'inventory = list_append(inventory, :items)',
                ExpressionAttributeValues: {
                    ':items': { L: [{ S: itemId }] },
                    ':price': { N: itemPrice.toString() }
                }
            }
        }
    ]
}).promise();

これまでもawslabsのJavaライブラリでdynamodb-transactionsはありましたが、ついに公式で提供されることになりました。

これまでサーバーレス開発部でもDBのロールバックが要件にある場合、RDSを選択せざるを得なかったのですが今回のアップデートによりDynamoDBの可能性が広がりました!!

ちなみにトランザクション機能による追加費用はありません。

追って検証記事も書いていきたいと思います!

参考

AWS News Blog