Distributed Concurrency Control
Scenario
Many concurrent request tries to book the same Movie theatre Seat.
Details: If we have many requests to book the same theatre seat then the status will be confirmed for all the users though the seat can be alloted only for one user.
Critical Section: The area or memory where multiple processes view or write the data is considered a critical section.
Steps involved in the booking process
{
Read Seat Row with ID: 10
If Free:
Logic to Change the Status from Free to Booked
Update the DB
}
Solution
1. Using SYNCHRONIZED for the Critical Section
Use synchronized
keyword. This block ensures that only one process can enter the critical section at a time.
synchronized ()
{
Read Seat Row with ID: 10
If Free:
Logic to Change the Status from Free to Booked;
Update the DB;
}
Drawback:
This approach will work for a process that has multiple threads.
This will not work for a distributed system (microservices) because each service is a separate process.
Note: A process can have multiple threads.
2. Using Distributed Concurrency Control
There are 2 types of Control
Optimistic Concurrency Control (OCC)
Pessimistic Concurrency Control (PCC)
Q) We must know below important things below first before concurrency control
What is the usage of Transaction?
The transaction helps to achieve INTEGRITY. This means it helps us to avoid INCONSISTENCY in our database
For example:
Debit the money from A and Credit the money to B
BEGIN_TRANSACTION: - Debit the Money from A - Credit the Money to B If all Success: COMMIT; else: ROLLBACK; END_TRANSACTION;
Explanation: If the bank balance of A and B are 50 and 60 respectively. If A transferred 20 to B then according to the transaction algorithm (above) it will debit 20 from A in the first step. Second step it will credit 20 to B. If all success it will commit the transaction. In case there is any issue in step 2 then it will roll back all the transactions above to it. This means A will be credited back to the 20.
If we don't use the transaction then db will be in an inconsistent state like money is debited from A but not credited to B.
What is DB Locking?
DB Locking, helps us to make sure that no other transaction updates the locked rows. There are 2 types of lock
a. Shared Lock (T(S)): If a transaction is accessing the memory in the shared lock then no other transactions cannot modified but they can only read the data in shared lock mode.
b. Exclusive Lock (T(X)): If a transaction is accessing memory in exclusive lock mode then no other transactions can access the same memory in exclusive lock or shared lock.
Lock Type | Another Shared Lock | Another Exclusive Lock |
Have Shared Lock | Yes | No |
Have Exclusive Lock | No | No |
Shared Lock
Exclusive Lock
Note: The lock mode of the memory is decided by the transaction that is currently accessing the memory. Hence any other transactions coming before the completion of the current process should follow the lock protocols as stated above.
- What is the Isolation Level present?
Isolation tells us how much concurrency is allowed in our application. This is part of ACID properties.
Isolation Level | Dirty Read Possible | Non-Repeatable Read Possible | Phantom Read Possible |
Read Uncommitted | Yes | Yes | Yes |
Read Committed | No | Yes | Yes |
Repeatable Read | No | No | Yes |
Serializable | No | No | No |
Read Types
- Dirty Read:
If Transaction A is reading the data that is written by Transaction B and has not yet even committed. If Transaction B does the rollback, then whatever data is read by Transaction A is known as a dirty read.
Time Stamp | Transaction A | Transaction A | DB |
T1 | BEGIN_TRANSACTION | BEGIN_TRANSACTION | ID: 1 |
Status: Free |
| T2 | | Update Row ID: 1;
Status: Booked; | ID: 1
Status: Booked
(Not yet committed by Transaction B) |
| T3 | Read Row ID: 1;
(Got status as Booked) | | ID: 1
Status: Booked
(Not yet committed by Transaction B) |
| T4 | Some Computation | Some issues faced here | ID: 1
Status: Booked
(Not yet committed by Transaction B) |
| T5 | Commit | Rollback | ID: 1
Status: Free |
- Non-Repeatable Read:
If Transaction A, reads the same row several times and there is a chance that it reads a different value.
Time Stamp | Transaction A | DB | |
T1 | BEGIN_TRANSACTION | ID: 1 |
Status: Free | |
| T2 | Read Row ID: 1;
(Status as Free) | ID: 1
Status: Free | |
| T3 | | ID: 1
Status: Booked | Some other Transactions changed and committed the changes. |
| T4 | Read Row ID: 1;
(Status as Booked) | ID: 1
Status: Booked | |
| T5 | Commit | | |
- Phantom Read:
If Transaction A executes the same query several times there is a chance that the rows returned are different.
Time Stamp | Transaction A | DB | |
T1 | BEGIN_TRANSACTION | ID: 1, Status: Free |
ID: 3, Status: Booked | |
| T2 | Read Row where ID>0 and ID<5
(reads 2
rows ID: 1 and ID: 3) | ID: 1, Status: Free
ID: 3, Status: Booked | |
| T3 | | ID: 1, Status: Free
ID: 2, Status: Free
ID: 3, Status: Booked | Some other Transaction inserted the row with ID: 2 and committed |
| T4 | Read Row where ID>0 and ID<5
(reads 3
rows ID: 1, ID: 2 and ID: 3) | ID: 1, Status: Free
ID: 2, Status: Free
ID: 3, Status: Booked | |
| T5 | Commit | | |
Isolation Types
Level | Isolation Level | Locking Strategy |
0 | Read Uncommitted | READ: No Lock acquired |
WRITE: No Lock acquired |
| 1 | Read Committed | READ: Shared Lock acquired and Released as soon as Read is done
WRITE: Exclusive Lock acquired keep till the end of the transaction |
| 2 | Repeatable Read | READ: Shared Lock acquired and Released only at the end of the Transaction
WRITE: Exclusive Lock acquired and Released only at the end of the Transaction |
| 3 | Serializable | Same as Repeatable Read Locking Strategy + Apply Range lock and lock is released only at the end of the Transaction |
Usage:
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
BEGIN_TRANSACTION;
SELECT Query;
Update Query;
If Success:
COMMIT TRANSACTION
else:
ROLLBACK_TRANSACTION
END_TRANSACTION
A. Optimistic Concurrency Control (OCC)
OCC uses the isolation level Read-Committed
Time Stamp | Transaction A | Transaction B | DB |
T1 | BEGIN_TRANSACTION | BEGIN_TRANSACTION | ID: 1 |
Status: Free
Version: 1 |
| T2 | Read Row ID: 1
(Row Version is 1) | Read Row ID: 1
(Row Version is 1) | ID: 1
Status: Free
Version: 1 |
| T3 | Select for Update
(Version Validation happens)
1==1? | | (Exclusive Lock -TxnA)
ID: 1
Status: Free
Version: 1 |
| T4 | Update
Row ID:1
Status: Booked
Version: 2 | | (Exclusive Lock -TxnA)
ID:1
Status: Booked
Version: 2 |
| T5 | COMMIT | | ID: 1
Status: Booked
Version: 2 |
| T6 | | Select for Update
(Version Validation happens)
1==2? | (Exclusive Lock -TxnB)
ID: 1
Status: Booked
Version: 2 |
| T7 | | ROLLBACK | ID: 1
Status: Booked
Version: 2 |
Transaction flow chart for OCC:
B. Pessimistic Concurrency Control
It uses either a Repeatable or serializable isolation level. Here it won't release the lock till the transaction is completed for shared lock.
Timestamp | Transaction A | Transaction B | DB |
T1 | BEGIN_TRANSACTION | BEGIN_TRANSACTION | ID: 1 |
Status: Free
ID: 2
Status: Free |
| T2 | Read Row ID: 1 | Read Row ID: 1 | Shared Lock (A & B)
ID: 1
Status: Free
Shared Lock (A)
ID: 2
Status: Free |
| T3 | Update Row ID: 2 | | Shared Lock (A & B)
ID: 1
Status: Free
Exclusive Lock (A)
ID: 2
Status: Booked |
| T4 | Some Computation | Some Computation | Shared Lock (A & B)
ID: 1
Status: Free
Exclusive Lock (A)
ID: 2
Status: Booked |
| T4 | COMMIT | COMMIT | Shared Lock (A & B)
ID: 1
Status: Free
Exclusive Lock (A)
ID: 2
Status: Booked |
| T5 | END_TRANSACTION
(Release Locks) | END_TRANSACTION
(Release Locks) | ID: 1
Status: Free
ID: 2
Status: Booked |
Dead Lock in PCC
T1 | T2 | DB | |
Read A | Read B | A - Shared Lock |
B - Shared Lock | |
| Write B | Write A | Wait..... | Waiting for A to be released by T1
Waiting for B to be released by T2 |
| Abort | Abort | A
B | After wait duration |
Dead Lock in OCC (Not possible)
T1 | T2 | DB |
Read A | Read B | A - Shared Lock |
B - Shared Lock |
| Read done | Read done | A
B |
| Write B | Write A | A - Exclusive Lock
B - Exclusive Lock |
OCC vs PCC
OCC | PCC |
Isolation level used Below REPEATABLE READ | Isolation level used REPEATABLE and SERIALIZABLE |
Much Higher Concurrency | Less Concurrency compared to Optimistic |
No chance of Deadlock | Deadlock is possible, then transactions stuck in deadlock are forced to do a rollback |
In case of conflict, the overhead of transaction rollback and retry logic is there | Putting a long lock, sometimes timeout issue comes and rollback needs to be done. |
Subscribe to my newsletter
Read articles from Chetan Datta directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Chetan Datta
Chetan Datta
I'm someone deeply engrossed in the world of software developement, and I find joy in sharing my thoughts and insights on various topics. You can explore my exclusive content here, where I meticulously document all things tech-related that spark my curiosity. Stay connected for my latest discoveries and observations.