2

I am currently using Dynamodb as database and NodeJS as backend. For every user, whenever I receive a request, I fetch that user's data from database, do some computation on the data at backend and at then end of request I update the data in the database.

The issue is that when a single user makes multiple requests at the same time, only some of updates are written on the database while the others are lost. Is there any way I can fix this issue.

For example, lets say I have a counter for each user and on every request I provide a value with which the counter will be incremented. So if I send 5 requests at the same time with value as 5, then the counter should increment by 25 but instead it only does with 10 or 15

I don't mind changing the database to mongodb if it can solve this issue

3 Answers 3

5

DynamoDB recommends you use Optimistic Locking for this:

https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBMapper.OptimisticLocking.html

With optimistic locking, each item has an attribute that acts as a version number. If you retrieve an item from a table, the application records the version number of that item. You can update the item, but only if the version number on the server side has not changed. If there is a version mismatch, it means that someone else has modified the item before you did. The update attempt fails, because you have a stale version of the item. If this happens, you simply try again by retrieving the item and then trying to update it. Optimistic locking prevents you from accidentally overwriting changes that were made by others. It also prevents others from accidentally overwriting your changes.

The basic idea is:

  • Each record has a version number
  • When you read a record and edit it, you increment the version number
  • On the UpdateItem or PutItem call you add a condition that this should only succeed, if the version number still has the same value it did when you read the record.

If it's about incrementing a counter, you can do that using the ADD operator in an UpdateItem call, then DynamoDB will handle the concurrency issue.

https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateItem.html

Sign up to request clarification or add additional context in comments.

2 Comments

This document only highlights for java. I have tried everywhere but cant find anything for NodeJS or JavaScript
It's about the concept, I've included an excerpt that explains the idea in more detail. You'd have to implement this yourself.
1

Explanation of Issue

Hey! AWS Engineer here. The issue is not database specific, but just your updating approach. It seems like you are doing something like the following:

  1. Read value from DDB
  2. update value in Node
  3. Write new Value back to DDB

This is super prone to race conditions. lets say we have requests A and B, and both try to read and increment a number n from the database by 1. You expect the final value to be n+2, however this happens...

A reads n,
A computes n = n+1,
B reads n, // ( old value )
A writes n+1, // where n used to be
B computes n = n+1,
B writes n+1, // where n+1 used to be, making A redundant 

As we can see, B does not wait for A to write the new value n before reading, so it gets an old value, making request A redundant.

Solution

In general, it is recommended to use direct update requests where possible instead of read + change + write to avoid this type of issue, regardless of what database you use.

Here, using DynamoDb's UpdateItem method would get rid of the race condition.

Just set the UpdateExpression parameter to "SET n = n + 1", as shown here in the documentation. Now if A and B run, the values are changed directly in the database with no delay, so it does not matter what order or how close together they run.

Note: If you only want the update to run under certain conditions, then you can specify this in the ConditionExpression parameter.

I hope this helps!

Comments

0

Because of concurrent updates you lose some data. You should use $incr operator to properly increment an attribute.

3 Comments

OP is not using Mongo (yet)
The counter is just an example. Actually whenever i read the values from DB, I perform some mathematical operations on it and update the record
Then you need some lock on a record, pessimistic or optimistic. Optimistic locking in dynamodb is described in the answer from @Maurice

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.