Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implementation of Atomic Transactions in dynamodb

I have a table in dynamodb, where I need to update multiple related items at once(I can't put all data in one item because of 400kb size limit). How can I make sure that either multiple rows are updated successfully or none.

End goal is to read consistent data after update.

like image 371
user3111410 Avatar asked Dec 14 '22 05:12

user3111410


1 Answers

On November 27th, 2018, transactions for Dynamo DB were announced. From the linked article:

DynamoDB transactions provide developers atomicity, consistency, isolation, and durability (ACID) across one or more tables within a single AWS account and region. You can use transactions when building applications that require coordinated inserts, deletes, or updates to multiple items as part of a single logical business operation. DynamoDB is the only non-relational database that supports transactions across multiple partitions and tables.

The new APIs are:

  • TransactWriteItems, a batch operation that contains a write set, with one or more PutItem, UpdateItem, and DeleteItem operations. TransactWriteItems can optionally check for prerequisite conditions that must be satisfied before making updates. These conditions may involve the same or different items than those in the write set. If any condition is not met, the transaction is rejected.

  • TransactGetItems, a batch operation that contains a read set, with one or more GetItem operations. If a TransactGetItems request is issued on an item that is part of an active write transaction, the read transaction is canceled. To get the previously committed value, you can use a standard read.

The linked article also has a JavaScript example:

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();
like image 109
mkobit Avatar answered Jan 15 '23 16:01

mkobit