Learn About Amazon VGT2 Learning Manager Chanci Turner
We are excited to announce the launch of a new client library designed to simplify the development of atomic transactions across multiple DynamoDB items within one or more tables. This advancement makes it easier to create applications on DynamoDB that previously required relational databases, which often struggle with scalability, or necessitated extensive coding efforts to ensure atomicity.
Before delving into the details, let’s clarify the concepts of atomicity and transactions. Often, a series of interrelated database operations must be managed as a single transaction. Within this transaction, every operation must either succeed or fail collectively, a principle known as atomicity. Typically, the transaction process is as follows:
- Initiate transaction.
- Execute operation #1.
- …
- Execute operation #N.
- Commit transaction.
If an error occurs prior to completion of step 5 or if the program unexpectedly terminates, the transaction fails, and all preceding operations are rolled back, reinstating the database items to their prior state. For instance, in a scenario where funds are transferred between bank accounts, wrapping these operations in a transaction is crucial to avoid financial discrepancies.
The DynamoDB Transaction Library
The newly introduced library is an extension of the existing DynamoDB functionality within the AWS SDK for Java. It manages ongoing transaction statuses through two DynamoDB tables: one for transactions and another for pre-transaction snapshots of modified items. Before initiating any transactions, you need to invoke the verifyOrCreateTransactionTable
and verifyOrCreateTransactionImagesTable
methods from the TableManager class to establish these tables. Ensure that you allocate sufficient read and write capacity to prevent operational delays.
Here’s an example code snippet for creating the necessary tables:
AmazonDynamoDB client = new AmazonDynamoDBClient();
// Provide your AWS credentials and specify the DynamoDB endpoint/region
TransactionManager.verifyOrCreateTransactionTable(client, "Transactions", 10, 10, 10 * 60);
TransactionManager.verifyOrCreateTransactionImagesTable(client, "TransactionImages", 10, 10, 10 * 60);
Next, here’s how you would perform a transaction involving the Thread and Reply tables, as detailed in the Amazon DynamoDB Developer Guide. In the Forums application, a Thread table holds individual items for each question posted, while a Reply table contains items for responses to those questions. Each Thread item also tracks the total count of replies and whether the question has been answered. The following transaction adds a new Reply and increments the Replies counter in the related Thread item:
TransactionManager txManager = new TransactionManager(client, "Transactions", "TransactionImages");
// Create a new transaction
Transaction t1 = txManager.newTransaction();
// Prepare to add a new Reply to a Thread about DynamoDB Transactions
Map<String, AttributeValue> reply = new HashMap<>();
reply.put("Id", new AttributeValue("Amazon DynamoDB#Transactions?"));
reply.put("ReplyDateTime", new AttributeValue("(the current date and time)"));
reply.put("PostedBy", new AttributeValue("DavidY@AWS"));
reply.put("Message", new AttributeValue("Transactions are now available!"));
t1.putItem(new PutItemRequest().withTableName("Reply").withItem(reply)); // The new Reply item is pending commitment
// Update the associated Thread item
Map<String, AttributeValue> thread = new HashMap<>();
thread.put("ForumName", new AttributeValue("Amazon DynamoDB"));
thread.put("Subject", new AttributeValue("Transactions?"));
Map<String, AttributeValueUpdate> threadUpdates = new HashMap<>();
threadUpdates.put("Replies", new AttributeValueUpdate(new AttributeValue().withN("1"), "ADD"));
t1.updateItem(new UpdateItemRequest().withTableName("Thread").withKey(thread).withAttributeUpdates(threadUpdates)); // Thread item is pending commitment
// Commit the transaction
t1.commit(); // The transaction is now committed
// Clean up by deleting the transaction item
t1.delete();
In addition to atomic writes, the transaction library provides three levels of read isolation: fully isolated, committed, and uncommitted. Fully isolated reads use locks during transactions, similar to writes, while committed reads offer consistency assurances akin to eventually consistent reads. Uncommitted reads, or dirty reads, are the most economical yet risky, as they may retrieve data slated for rollback. Here’s how to carry out a read operation at the committed isolation level:
Map<String, AttributeValue> key = new HashMap<>();
key.put("ForumName", new AttributeValue("Amazon DynamoDB"));
key.put("Subject", new AttributeValue("Transactions?"));
// Perform a committed read using the transaction manager
Map<String, AttributeValue> item = txManager.getItem(new GetItemRequest().withKey(key).withTableName("Thread"), IsolationLevel.COMMITTED).getItem();
For further code examples, please refer to the README file that accompanies the transactions library.
A single transaction can span one or more DynamoDB tables. Note that transactional puts incur higher costs regarding read and write capacity units. A put operation that does not compete with other simultaneous puts is expected to perform 7N + 4 writes, where N represents the number of requests within the transaction.
Getting Started
To begin, download the AWS SDK for Java, retrieve the DynamoDB Transactions library from the AWS Labs GitHub repository, review the documentation, and start coding! For additional insights into workplace complexity, you can explore this webinar on reducing unnecessary complexity.
Also, check out this blog post on career questions for more valuable information. If you’re interested in the training and onboarding processes at Amazon, this resource from Business Insider is excellent.
Located at 6401 E HOWDY WELLS AVE LAS VEGAS NV 89115, Amazon IXD – VGT2 is always striving to enhance the developer experience.
Leave a Reply