Serializability of schedules
Two operations conflict if:
- They belong to different transactions
- They operate on the same data
- One of them is a write
Two schedules are equivalent if
- They involve the same transactions and operations
- All conflicting operations are ordered the same way
A schedule is serializable only if it is equivalent to a serial schedule.
Testing for serializability
Intuition: swap non-conflicting operations until you reach a serial schedule.
Example 1
Suppose conflicting operations (blue):

By swapping non-conflicting operations, you can achieve a serial schedule:

Example 2
Suppose another conflicting operations:

After attempting to swap non-conflicting operations, the schedule is not serializable:

Another way to test serializability
Another way to test serializability:
- Draw arrows between conflicting operations
- Arrow points in the direction of time
- If no cycles between transactions, the schedule is serializable
Example 1
Draw arrow between conflicting operations:

No cycle is found, thus serializable.
Example 2
Draw arrows between conflicting operations:

A cycle is found, thus not serializable
Implementing serializability: 2PL
2PL guarantees serializability by disallowing cycles between transactions.
There could be dependencies in the waits-for graph among transactions waiting for locks:
- Edge from T2 to T1 means T2 is waiting for the lock acquired by T1
- Edge from T1 to T2 means T1 is waiting for the lock acquired by T2
- Cycles mean deadlock, and in this case 2PL won’t proceed
Deadlock Example
Observe waits-for graph creating a cycle:

You can deal with deadlocks by aborting one of the two transactions by detecting with timeout.
Releasing locks too early
Suppose another example with plain 2PL:

Suppose initially:
A = 100
T1 changes it:
R(A) = 100
W(A) = 200
But T1 has not committed yet.
Under basic 2PL, T1 is allowed to release its lock on A before commit as long as it never acquires another lock afterward:
Lock-X(A)
R(A)
W(A)
Unlock-X(A)
The problem is when T2 reads R(B) = 200, it is an uncommitted value.
Imagine T1 later discovers an error and has to abort, causing it to rollback A = 100.
Therefore, everything T2 did based on A = 200 is invalid, so T2 has to abort as well.
This sequence of aborts is known as cascading abort.
This degrades performance.
Strict 2PL
Strict 2PL adds another rule to prevent uncommitted values to be read by other transaction:
- Do not release write locks until the transaction commits or aborts.
- Variant of 2PL implemented by most databases in practice
For example, the T1 released the lock after the abort:
T1: X(A) R(A) W(A) -------- ABORT → rollback → unlock(A)
|
| T2 waits
↓
T2: WAIT ------------------> S(A) R(A)
↑
restored value
T2 can proceed with its operations regardless of T1 abortion.
If abort didn’t happen:
T1: X(A) R(A) W(A) -------- commit → unlock(A)
|
| T2 waits
↓
T2: WAIT ------------------> S(A) R(A) = 200
The transactions succeed normally.
Two ways of implementing serializability: 2PL, OCC
2PL (pessimistic):
- Assume conflicts are prevalent so ensures lock always
- High overhead for non-conflicting transactions
- Must check for deadlock
Optimistic concurrency control (OCC):
- Assume conflicts are not prevalent
- Low overhead for non-conflicting transactions, but high for conflicting transactions
- Ensure correctness by aborting transactions if conflict occurs
Optimistic concurrency control
- Execute optimistically: Read committed values, write changes locally
- Validate: Check if data has changed since original read
- Commit (Write): Commit if no change, else abort
Atomic commit for OCC
Use two-phase commit (2PC) to achieve atomic commit (validate + commit writes)
Phase 1: send prepare to each shard: include buffered write + original read for that shard
- Shards validate reads and acquire locks (exclusive for write locations, shared for read locations)
- If this succeeds, respond with yes; else respond with no
Phase 2: collect votes, send result (abort or commit) to all shards
- If commit, shards apply buffereed writes
- All shards release locks