Conflict Serializability
Precedence Graph
Read aloud is unavailable in this browser.
The Algorithm That Makes Serializability Practical
All our theoretical groundwork—schedules, serial schedules, equivalence, conflicts—culminates in this page. The precedence graph (also called serializability graph or serialization graph) transforms the abstract question "Is this schedule conflict-serializable?" into a concrete, efficient algorithm.
The precedence graph method is:
- Complete: It correctly identifies ALL conflict-serializable schedules
- Sound: Every schedule it accepts IS conflict-serializable
- Efficient: Runs in polynomial time O(n² × m²) where n = transactions, m = operations
- Constructive: When serializable, it provides an equivalent serial order
This is the standard algorithm taught in every database course and serves as the foundation for understanding how real concurrency control protocols work. Whether you're analyzing schedules manually, implementing a database scheduler, or understanding isolation levels, the precedence graph is your essential tool.
By the end of this page, you will be able to construct a precedence graph from any schedule, detect cycles using DFS or other methods, extract an equivalent serial order via topological sort when serializable, and analyze various schedules to determine their serializability status with complete confidence.
Precedence Graph: Definition and Intuition
Formal Definition
Given a schedule S over transactions T = {T₁, T₂, ..., Tₙ}, the precedence graph G(S) = (V, E) is a directed graph where:
Vertices (V): One vertex for each transaction Tᵢ in S
Edges (E): A directed edge Tᵢ → Tⱼ exists if and only if there is a conflict between Tᵢ and Tⱼ where Tᵢ's operation appears before Tⱼ's operation in S
(Tᵢ → Tⱼ) ∈ E ⟺ ∃ conflicting operations oᵢ ∈ Tᵢ, oⱼ ∈ Tⱼ
such that oᵢ <S oⱼ (oᵢ precedes oⱼ in S)
Intuition: Ordering Constraints as Edges
Each edge represents an ordering constraint:
- Tᵢ → Tⱼ means "Tᵢ must come before Tⱼ in any equivalent serial schedule"
Why? Because there's a conflict where Tᵢ's operation happens first. In any equivalent serial schedule, this ordering must be preserved, which means Tᵢ must complete entirely before Tⱼ starts.
Edge Types by Conflict
Edges arise from three types of conflicts:
| Conflict | Operations | Edge Meaning |
|---|---|---|
| RW | rᵢ(X) <S wⱼ(X) | Tᵢ reads before Tⱼ writes |
| WR | wᵢ(X) <S rⱼ(X) | Tⱼ reads Tᵢ's value |
| WW | wᵢ(X) <S wⱼ(X) | Tⱼ's write overwrites Tᵢ's |
All three create the same type of edge: Tᵢ → Tⱼ
Multiple conflicts between the same pair: If there are multiple conflicts between Tᵢ and Tⱼ (e.g., on different data items), they might create edges in the same direction (Tᵢ → Tⱼ) or opposite directions (Tᵢ → Tⱼ and Tⱼ → Tᵢ). Opposite-direction edges between the same pair form a cycle of length 2.
Multiple conflicts creating the same edge (e.g., two RW conflicts both giving T₁ → T₂) don't result in multiple edges. We only care whether an edge exists, not how many conflicts created it. The precedence graph is a simple directed graph, not a multigraph.
Precedence Graph Construction Algorithm
Step-by-Step Algorithm
Algorithm: ConstructPrecedenceGraph(S)
Input: Schedule S over transactions T = {T₁, T₂, ..., Tₙ}
Output: Precedence graph G = (V, E)
1. Initialize G:
- V = {T₁, T₂, ..., Tₙ} // One vertex per transaction
- E = ∅ // Empty edge set initially
2. For each data item X accessed in S:
a. Collect all operations on X in schedule order
b. For each pair of operations (oᵢ, oⱼ) on X where:
- oᵢ ∈ Tᵢ and oⱼ ∈ Tⱼ with i ≠ j
- oᵢ appears before oⱼ in S
- At least one of oᵢ, oⱼ is a write
Add edge Tᵢ → Tⱼ to E (if not already present)
3. Return G = (V, E)
Complexity Analysis
- Step 2a: For each data item, O(m) operations to collect
- Step 2b: For each pair C(m,2) = O(m²) pairs to check
- With d data items: O(d × m²) conflict checks
- Each check is O(1), edge insertion is O(1) with hash set
- Total: O(d × m²) or equivalently O(n² × m²) where n = transactions
Constructing a Precedence Graph
Build the precedence graph for the given schedule:
Schedule S:
r₁(A) r₂(A) w₂(A) w₁(A) r₁(B) r₂(B) w₂(B) w₁(B)
Positions:
1: r₁(A) 2: r₂(A) 3: w₂(A) 4: w₁(A)
5: r₁(B) 6: r₂(B) 7: w₂(B) 8: w₁(B)Step 1: Initialize
- V = {T₁, T₂}
- E = ∅
Step 2a: Data item A
Operations: r₁(A)@1, r₂(A)@2, w₂(A)@3, w₁(A)@4
Conflict pairs:
- r₁(A)@1, w₂(A)@3: RW, T₁ before T₂ → add T₁ → T₂
- r₂(A)@2, w₁(A)@4: RW, T₂ before T₁ → add T₂ → T₁
- w₂(A)@3, w₁(A)@4: WW, T₂ before T₁ → T₂ → T₁ (already added)
Step 2b: Data item B
Operations: r₁(B)@5, r₂(B)@6, w₂(B)@7, w₁(B)@8
Conflict pairs:
- r₁(B)@5, w₂(B)@7: RW, T₁ before T₂ → T₁ → T₂ (already added)
- r₂(B)@6, w₁(B)@8: RW, T₂ before T₁ → T₂ → T₁ (already added)
- w₂(B)@7, w₁(B)@8: WW, T₂ before T₁ → T₂ → T₁ (already added)
Final Graph:
T₁ ⟷ T₂ (bidirectional = cycle!)
Edges: E = {T₁ → T₂, T₂ → T₁}Explanation
The graph has edges in both directions between T₁ and T₂. This is a cycle of length 2. The schedule is NOT conflict-serializable because there's no way to order T₁ and T₂ consistently.
Processing conflicts data-item by data-item is systematic and reduces errors. For each data item, list all operations in schedule order, then check every pair involving at least one write. This ensures you don't miss any conflicts.
The Serializability Theorem
The Fundamental Theorem
Theorem (Conflict Serializability Test):
A schedule S is conflict-serializable if and only if its precedence graph G(S) is acyclic.
S is conflict-serializable ⟺ G(S) is acyclic
Proof Sketch
If direction (Acyclic → Serializable):
If G(S) is acyclic, it has a topological ordering T_{π(1)}, T_{π(2)}, ..., T_{π(n)}. This ordering respects all edges: if Tᵢ → Tⱼ, then Tᵢ appears before Tⱼ.
Construct serial schedule Ss = T_{π(1)} · T_{π(2)} · ... · T_{π(n)}.
For every conflict oᵢ <S oⱼ in S, we have edge Tᵢ → Tⱼ in G(S), which means Tᵢ comes before Tⱼ in the topological order, so oᵢ <Ss oⱼ in Ss.
Thus S ≡c Ss (all conflicts have same ordering). Therefore S is conflict-serializable.
Only if direction (Serializable → Acyclic):
Suppose G(S) has a cycle: Tᵢ₁ → Tᵢ₂ → ... → Tᵢₖ → Tᵢ₁
This means:
- Tᵢ₁ must precede Tᵢ₂ in any equivalent serial schedule
- Tᵢ₂ must precede Tᵢ₃
- ...
- Tᵢₖ must precede Tᵢ₁
By transitivity: Tᵢ₁ must precede itself. Contradiction!
No serial schedule can satisfy all constraints, so S is not conflict-serializable.
To test conflict serializability: (1) Construct the precedence graph G(S), (2) Check if G(S) is acyclic. If acyclic → serializable, find equivalent serial order via topological sort. If cyclic → not serializable, the cycle shows the contradiction.
| Graph Status | Serializability | Action |
|---|---|---|
| Acyclic | Conflict-serializable ✓ | Topological sort gives serial order |
| Cyclic | Not conflict-serializable ✗ | Cycle shows why |
Cycle Detection in Precedence Graphs
Method 1: Depth-First Search (DFS)
The standard algorithm for cycle detection in directed graphs:
Algorithm: HasCycle(G)
Input: Directed graph G = (V, E)
Output: True if G has a cycle, False otherwise
1. color[v] = WHITE for all v ∈ V
// WHITE = unvisited, GRAY = in progress, BLACK = finished
2. For each vertex v ∈ V:
If color[v] = WHITE:
If DFS-Visit(v) returns True:
Return True // Cycle found
3. Return False // No cycle
DFS-Visit(u):
1. color[u] = GRAY
2. For each neighbor v of u:
If color[v] = GRAY:
Return True // Back edge = cycle!
If color[v] = WHITE:
If DFS-Visit(v) returns True:
Return True
3. color[u] = BLACK
4. Return False
Complexity: O(V + E) = O(n + edges) where edges ≤ n² for n transactions
Method 2: Topological Sort Attempt
Trying to compute a topological sort also detects cycles:
Algorithm: TopologicalSort(G)
Input: Directed graph G = (V, E)
Output: Topological ordering if acyclic, CYCLE if cyclic
1. Compute in-degree for each vertex
2. Queue = all vertices with in-degree 0
3. result = empty list
4. While Queue is not empty:
a. u = dequeue
b. Append u to result
c. For each edge (u, v):
- Decrement in-degree[v]
- If in-degree[v] = 0:
Enqueue v
5. If |result| = |V|:
Return result // Valid topological order
Else:
Return CYCLE // Some vertices unreachable = cycle exists
Complexity: O(V + E)
Method 3: Quick Check for 2-Cycles
For small precedence graphs, check for bidirectional edges:
For each pair (Tᵢ, Tⱼ):
If edge Tᵢ → Tⱼ exists AND edge Tⱼ → Tᵢ exists:
Return CYCLE
This catches the most common case: two transactions with conflicts in both directions.
For exam/academic purposes, visual inspection often suffices for small graphs. Look for: (1) bidirectional edges (immediate 2-cycle), (2) any path from a vertex back to itself. For implementation, DFS-based detection or Kahn's topological sort algorithm are both O(V + E) and straightforward.
Finding Equivalent Serial Orders
When the precedence graph is acyclic, we can find an equivalent serial schedule using topological sort.
Understanding Topological Sort
A topological sort of a directed acyclic graph (DAG) is a linear ordering of vertices such that for every edge (u, v), u appears before v in the ordering.
Key Insight: For an acyclic precedence graph, any topological sort gives a valid equivalent serial schedule.
Multiple Valid Orders
If the graph has multiple valid topological sorts, all of them are equivalent serial schedules!
Graph: T₁ → T₃, T₂ → T₃
Valid topological sorts:
- T₁, T₂, T₃ ✓
- T₂, T₁, T₃ ✓
Both are valid serial schedules equivalent to the original.
Finding the Equivalent Serial Schedule
Given schedule S, find an equivalent serial schedule:
S: r₂(A) r₁(B) w₂(A) r₃(A) w₁(B) w₃(A)
Transactions: T₁, T₂, T₃Step 1: Construct Precedence Graph
Data item A: r₂(A)@1, w₂(A)@3, r₃(A)@4, w₃(A)@6
- r₂(A)@1, w₃(A)@6: RW → T₂ → T₃
- w₂(A)@3, r₃(A)@4: WR → T₂ → T₃ (already)
- w₂(A)@3, w₃(A)@6: WW → T₂ → T₃ (already)
Data item B: r₁(B)@2, w₁(B)@5
- Only T₁ operations → No inter-transaction conflicts
Graph edges: E = {T₂ → T₃}
Vertices: {T₁, T₂, T₃}
Step 2: Check for cycles
- No edge into T₁
- No edge into T₂
- Only T₂ → T₃ edge
- No cycles!
Step 3: Topological sort
In-degrees: T₁=0, T₂=0, T₃=1
Start with T₁ and T₂ (both have in-degree 0)
Possible orders:
- T₁, T₂, T₃ ✓
- T₂, T₁, T₃ ✓
- T₂, T₃, T₁ ✗ (T₃ must come after T₂)
Wait... T₁ has no constraints with T₂ or T₃!
Actually valid orders:
- T₁, T₂, T₃
- T₂, T₁, T₃
- T₂, T₃, T₁
- T₁, T₂, T₃ (where T₁ can go anywhere)
Let's verify: T₂, T₃, T₁
- T₂ → T₃ satisfied ✓
- No constraints on T₁ ✓
All these are valid equivalent serial schedules!Explanation
When a transaction has no edges (T₁ in this case), it can appear anywhere in the serial order. The only constraint is T₂ → T₃, so T₂ must precede T₃. T₁ is independent and can be placed anywhere.
Transactions with no edges in the precedence graph (no conflicts with other transactions) can be placed anywhere in the serial order. They access completely disjoint data sets from other transactions and are truly independent.
Comprehensive Worked Examples
Let's work through several complete examples to solidify your understanding.
Example 1: Three-Transaction Serializable Schedule
Example 1: Serializable
Analyze schedule S₁:
S₁: r₁(A) w₁(A) r₂(A) w₂(A) r₂(B) w₂(B) r₃(B) w₃(B)
Transactions: T₁, T₂, T₃
Data items: A, BConflict Analysis:
Data item A: r₁(A), w₁(A), r₂(A), w₂(A)
- w₁(A) → r₂(A): WR → T₁ → T₂
- w₁(A) → w₂(A): WW → T₁ → T₂ (redundant)
- r₁(A) → w₂(A): RW → T₁ → T₂ (redundant)
Data item B: r₂(B), w₂(B), r₃(B), w₃(B)
- w₂(B) → r₃(B): WR → T₂ → T₃
- w₂(B) → w₃(B): WW → T₂ → T₃ (redundant)
- r₂(B) → w₃(B): RW → T₂ → T₃ (redundant)
Precedence Graph:
T₁ → T₂ → T₃
Cycle check: No cycles (linear chain)
Topological sort: T₁, T₂, T₃
✓ S₁ is conflict-serializable
Equivalent to serial schedule: T₁ T₂ T₃Explanation
The schedule naturally follows a serial order pattern. All conflicts point in the same direction, creating a simple chain T₁ → T₂ → T₃.
Example 2: Non-Serializable Schedule
Example 2: Non-Serializable
Analyze schedule S₂:
S₂: r₁(A) r₂(A) r₃(B) w₁(A) r₂(B) w₃(B) w₂(A) w₂(B)
Transactions: T₁, T₂, T₃
Data items: A, BPositions:
1: r₁(A) 2: r₂(A) 3: r₃(B) 4: w₁(A)
5: r₂(B) 6: w₃(B) 7: w₂(A) 8: w₂(B)
Conflict Analysis:
Data item A: r₁(A)@1, r₂(A)@2, w₁(A)@4, w₂(A)@7
- r₁(A)@1 vs w₂(A)@7: RW → T₁ → T₂
- r₂(A)@2 vs w₁(A)@4: RW → T₂ → T₁ ⚠️
- w₁(A)@4 vs w₂(A)@7: WW → T₁ → T₂
Data item B: r₃(B)@3, r₂(B)@5, w₃(B)@6, w₂(B)@8
- r₃(B)@3 vs w₂(B)@8: RW → T₃ → T₂
- r₂(B)@5 vs w₃(B)@6: RW → T₂ → T₃ ⚠️
- w₃(B)@6 vs w₂(B)@8: WW → T₃ → T₂
Precedence Graph Edges:
- T₁ → T₂ (from A)
- T₂ → T₁ (from A) ⚠️ 2-cycle!
- T₃ → T₂ (from B)
- T₂ → T₃ (from B) ⚠️ 2-cycle!
Cycles found:
- T₁ ↔ T₂ (bidirectional)
- T₂ ↔ T₃ (bidirectional)
✗ S₂ is NOT conflict-serializableExplanation
Multiple 2-cycles exist. T₁ and T₂ have conflicting requirements on data item A. T₂ and T₃ have conflicting requirements on data item B. No serial order can satisfy all constraints.
Example 3: Complex Four-Transaction Schedule
Example 3: Four Transactions
Analyze schedule S₃:
S₃: r₄(D) r₁(A) w₄(D) r₂(B) w₁(A) r₃(C) w₂(B) w₃(C) r₄(A)
Transactions: T₁, T₂, T₃, T₄
Data items: A, B, C, DConflict Analysis:
Data item A: r₁(A)@2, w₁(A)@5, r₄(A)@9
- w₁(A)@5 vs r₄(A)@9: WR → T₁ → T₄
Data item B: r₂(B)@4, w₂(B)@7
- Only T₂, no conflicts with others
Data item C: r₃(C)@6, w₃(C)@8
- Only T₃, no conflicts with others
Data item D: r₄(D)@1, w₄(D)@3
- Only T₄, no conflicts with others
Precedence Graph:
- Only edge: T₁ → T₄
- T₂ and T₃ are completely independent
Graph visualization:
T₂
T₁ → T₄
T₃
Cycle check: No cycles!
Topological sorts (all valid):
- T₁, T₂, T₃, T₄
- T₂, T₁, T₃, T₄
- T₃, T₂, T₁, T₄
- T₂, T₃, T₁, T₄
- ... (many more, T₂ and T₃ can go anywhere, T₁ before T₄)
✓ S₃ is conflict-serializable
Constraint: T₁ must precede T₄. T₂, T₃ are independent.Explanation
When transactions access disjoint data sets, they don't create edges in the precedence graph. Only T₁ and T₄ share data item A, creating the single constraint.
Common Patterns and Shortcuts
Experienced analysts recognize patterns that immediately indicate serializability or non-serializability.
Quick Non-Serializability Indicators
Pattern 1: The Read-Write Swap
... rᵢ(X) ... wⱼ(X) ... rⱼ(Y) ... wᵢ(Y) ...
Creates: Tᵢ → Tⱼ (from X) and Tⱼ → Tᵢ (from Y)
2-cycle guaranteed!
Pattern 2: The Write-Write Swap
... wᵢ(X) ... wⱼ(X) ... wⱼ(Y) ... wᵢ(Y) ...
Creates: Tᵢ → Tⱼ (from X) and Tⱼ → Tᵢ (from Y)
2-cycle guaranteed!
Pattern 3: Bidirectional Access
Tᵢ reads X before Tⱼ writes X
Tⱼ reads Y before Tᵢ writes Y
Almost always creates a cycle. Check carefully!
Quick Serializability Indicators
Pattern 1: Monotonic Access
If all conflicts for all data items favor the same direction:
All edges: T₁ → T₂, T₁ → T₃, T₂ → T₃ (all point 'forward')
No back edges → acyclic → serializable
Pattern 2: Serial-Like Structure
If the schedule looks like T₁ operations, then T₂ operations, etc. (with minor interleaving of non-conflicting operations), likely serializable.
Pattern 3: Disjoint Access
Transactions accessing completely different data create no conflicts and add no edges:
T₁: operates on A, B
T₂: operates on C, D
No shared data → no edges → any serial order works
In exams: (1) First check for obvious 2-cycles—pairs of transactions with conflicts in both directions, (2) If no 2-cycles, build the full graph and look for longer cycles, (3) Draw the graph—visual inspection catches cycles faster than mental tracking. For 2-3 transactions, cycles are usually 2-cycles between a single pair.
| Observation | Likely Status | Verify By |
|---|---|---|
| Bidirectional edges exist | Non-serializable | 2-cycle immediately visible |
| All edges point one direction | Serializable | Confirm no back paths exist |
| Transactions share no data | Serializable | No edges = any order valid |
| Complex interleaving | Must analyze | Full graph + DFS for cycles |
KEEP LEARNING
There’s more to understand.
You’re reading the introduction. Create a free account to read the complete lesson, save notes and keep track of your progress.