Reputation: 990
So, it might seems like a very noob question, but after some googling, I couldn't find out the best approach.
Problem : Have a Spring-Boot application, interacting with the DataBase (MySQL). Consider a table T1, where I wan't to have only a single valid entry for each user. So if next entry appears, it soft-deletes (by setting the deleted-at column) the existing rows for that user and creates a new entry. Now the problem comes when there is are multiple request, almost at the same time.
My Transactional block, looks something like this :
@Transactional
someMethod() {
CheckIfAnyValidEntryForUser(U1);
SoftDeleteExistingEntries(U1);
DoComputation(); // Takes around a second.
InsertNewRow();
}
Now if there are multiple request within short span of time, so my code ends up inserting multiple valid entries for a single user.
Since the row I want to edit might not exist before, so I can't do Optimistic Locking by version number.
Was thinking of acquiring a Global-Lock on this someMethod, but this increase my latency by too much.
Another approach might be to use a composite unique key in the database for columns (including the deleted-at column). And then handle the commit failure in the code.
This seems to be a very common problem, so how is this handled usually? What is the best approach?
Upvotes: 1
Views: 4463
Reputation: 2817
You can use the isolation
property of @Transactional
annotation and set this property to Isolation.SERIALIZABLE
:
@Transactional(isolation= Isolation.SERIALIZABLE)
Note that :
Spring by default use DEFAULT isolation strategy which uses the default isolation level of underlying datastore. Using SERIALIZABLE isolation makes your transactions executed with locking at read, write, range; so they appear as if they were executed in a serialized way, preventing dirty reads, non-repeatable reads and phantom reads.
Also
Exclusively designed for use with Propagation.REQUIRED or Propagation.REQUIRES_NEW since it only applies to newly started transactions. Consider switching the "validateExistingTransactions" flag to "true" on your transaction manager if you'd like isolation level declarations to get rejected when participating in an existing transaction with a different isolation level.
Upvotes: 1