In modern distributed systems, multiple users or applications often access and modify the same data concurrently. Without proper control, this can lead to inconsistent data, race conditions, or system crashes. This is where Distributed Concurrency Control (DCC) comes in—a set of techniques to manage concurrent operations safely across distributed databases.
What is Distributed Concurrency Control?
Managing Bank Transactions Safely Across Systems
Imagine a customer, Alice, transferring money between her savings and checking accounts in a distributed banking system. At the same time, another transaction is trying to deduct a loan payment from her checking account.
Without proper coordination, these concurrent operations could overwrite each other, causing incorrect balances or inconsistent states. Distributed Concurrency Control ensures such conflicts are managed safely across multiple nodes.
Key Goals:
- Consistency: Database remains in a valid state after transactions.
- Isolation: Transactions behave as if executed one after another.
- Atomicity: Each transaction completes fully or not at all.
Bank Transaction Scenario
Initial State:
Account | Balance |
---|---|
Savings | 5000 |
Checking | 2000 |
Transactions:
- T1 (Savings → Checking transfer): Transfer 1000 from Savings to Checking.
- T2 (Loan Payment): Deduct 1500 from Checking.
Types of Distributed Concurrency Control
There are two main strategies for managing concurrency in distributed systems:
- Pessimistic Concurrency Control (PCC)
- Optimistic Concurrency Control (OCC)
1. Pessimistic Concurrency Control (PCC)
- PCC assumes conflicts between transactions are likely. It prevents conflicts by locking data before accessing it. If another transaction wants the same data, it must wait.
- PCC assumes conflicts are likely and prevents them upfront using locks.
Code:
// T1: Transfer Money
lock(savingsAccount, EXCLUSIVE);
lock(checkingAccount, EXCLUSIVE);
savingsAccount.balance -= 1000;
checkingAccount.balance += 1000;
commit();
unlock(savingsAccount, checkingAccount);
// T2 will wait for locks
lock(checkingAccount, EXCLUSIVE);
checkingAccount.balance -= 1500;
commit();
unlock(checkingAccount);
How it works?
Time | T1 (Transfer) | T2 (Loan Payment) |
---|---|---|
t1 | LOCK Savings (X-lock) | |
t2 | LOCK Checking (X-lock) | |
t3 | Deduct 1000 from Savings | |
t4 | Add 1000 to Checking | BLOCKED (Waiting for X-lock) |
t5 | COMMIT & Release Locks | LOCK Checking → Deduct 1500 |
t6 | COMMIT |
Key Points:
- Locks prevent conflicts.
- Other transactions wait until locks are released.
- Suitable for Repeatable Read and Serializable isolation levels.
Pessimistic Concurrency Control Example
T1: [LOCK Savings+Checking] → [UPDATE] → [COMMIT]
T2: [WAIT] → [LOCK] → [UPDATE] → [COMMIT]
Advantages of PCC:
- Prevents conflicts proactively.
- Suitable for high-conflict environments.
Disadvantages:
- Locks can cause deadlocks.
- Reduced concurrency if many transactions wait for locks.
2. Optimistic Concurrency Control (OCC)
OCC assumes conflicts are rare, so it does not lock data. Transactions proceed and validate at commit.
Code ->
# T1: Transfer Money
savings_local = read(savingsAccount)
checking_local = read(checkingAccount)
savings_local -= 1000
checking_local += 1000
if validate(savingsAccount, checkingAccount):
write(savingsAccount, savings_local)
write(checkingAccount, checking_local)
else:
abort_and_retry()
# T2: Loan Payment
checking_local = read(checkingAccount)
checking_local -= 1500
if validate(checkingAccount):
write(checkingAccount, checking_local)
else:
abort_and_retry()
How it works?
Time | T1 (Transfer) | T2 (Loan Payment) |
---|---|---|
t1 | Read Savings = 5000, Checking = 2000 | Read Checking = 2000 |
t2 | Update local copies | Update local copy |
t3 | Validate → no conflicts | Validate → conflict detected |
t4 | Commit: Savings = 4000, Checking = 3000 | ABORT → retry |
Key Points:
- Transactions proceed without locks.
- Conflicts detected at commit trigger retries.
- Suitable for Read Uncommitted and Read Committed isolation levels.
Optimistic Concurrency Control Example
T1: [READ local copy] → [UPDATE local] → [VALIDATE PASS] → [COMMIT]
T2: [READ local copy] → [UPDATE local] → [VALIDATE FAIL] → [RETRY]
Advantages of OCC:
- No locking overhead.
- High concurrency in low-conflict environments.
Disadvantages:
- Transactions may need to retry frequently in high-conflict scenarios.
- Requires careful validation logic.
How PCC and OCC Map to Isolation Levels
Concurrency Control | Isolation Levels it Supports | Notes |
---|---|---|
Pessimistic (PCC) | Repeatable Read, Serializable | Locks prevent dirty & non-repeatable reads, ensures serializability |
Optimistic (OCC) | Read Committed, Read Uncommitted | Validation ensures committed data, allows higher concurrency |
Top comments (0)