4
votes

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.

2

2 Answers

10
votes

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();
2
votes

You can use an API like this one for Java, http://aws.amazon.com/blogs/aws/dynamodb-transaction-library/. The transaction library API will help you manage atomic transactions.

If you're using node.js, there are other solutions for that using an atomic counter or conditional writes. See answer here, How to support transactions in dynamoDB with javascript aws-sdk?.