Circular Wait: Two or more transactions wait for each other indefinitely
Resource Dependency: Transaction A waits for resource held by Transaction B, which waits for resource held by Transaction A
System State: No transaction can proceed without external intervention
Database Problem: Common issue in concurrent database systems
Deadlock Conditions (Must All Be Present)
1. Mutual Exclusion
Resource Access: Only one transaction can hold a resource at a time
Lock Types: Exclusive locks prevent sharing
Example: Row-level exclusive locks for updates
2. Hold and Wait
Partial Allocation: Transaction holds some resources while requesting others
Progressive Locking: Acquiring locks throughout transaction lifecycle
Example: Hold lock on Table A while requesting lock on Table B
3. No Preemption
Voluntary Release: Resources can only be released by holding transaction
No Forced Release: System cannot forcibly take resources away
Database Context: Locks held until transaction commits/aborts
4. Circular Wait
Chain Formation: Closed loop of transactions waiting for each other
Dependency Cycle: Transaction A → B → C → A
Breaking Point: Must break cycle to resolve deadlock
Simple Deadlock Example
Scenario: Concurrent Inserts
Transaction 1
Transaction 2
BEGIN TRANSACTION;
BEGIN TRANSACTION;
INSERT INTO TEST VALUES (21);
INSERT INTO TEST VALUES (20);
INSERT INTO TEST VALUES (20); ← Waits
INSERT INTO TEST VALUES (21); ← Waits
Blocked: Waiting for row 20
Blocked: Waiting for row 21
Result: Deadlock detected by database
Resolution: One transaction rolled back
Why This Deadlocks
Transaction 1: Holds lock on row 21, wants lock on row 20
Transaction 2: Holds lock on row 20, wants lock on row 21
Circular Dependency: Neither can proceed
Database Action: Automatically detects and resolves
Common Deadlock Scenarios
1. Resource Ordering Conflict
-- Transaction AUPDATE accounts SET balance = balance - 100 WHERE id = 1;UPDATE accounts SET balance = balance + 100 WHERE id = 2;-- Transaction B (same time)UPDATE accounts SET balance = balance - 50 WHERE id = 2;UPDATE accounts SET balance = balance + 50 WHERE id = 1;
2. Index Lock Conflicts
-- Transaction AUPDATE users SET name = 'Alice' WHERE email = 'alice@example.com';-- Transaction BUPDATE users SET email = 'bob@new.com' WHERE name = 'Bob';
3. Foreign Key Deadlocks
-- Transaction AINSERT INTO orders (customer_id, amount) VALUES (1, 100);UPDATE customers SET total_orders = total_orders + 1 WHERE id = 1;-- Transaction BDELETE FROM customers WHERE id = 1;
Transaction Age: Sometimes prefer newer transactions
Lock Count: Consider number of locks held
Resolution Steps
Detect Deadlock: Identify circular wait condition
Choose Victim: Select transaction to abort
Rollback Transaction: Undo all changes made by victim
Release Locks: Free all resources held by victim
Notify Application: Return deadlock error to client
Error Handling
-- Application should retry after deadlockBEGIN TRANSACTION;-- ... operations ...COMMIT;-- If deadlock detected, transaction automatically rolled back-- Application receives deadlock error and should retry
Deadlock Prevention Strategies
1. Resource Ordering
Consistent Order: Always acquire resources in same order
Example: Always update accounts in ascending ID order
Implementation: Sort resource IDs before acquiring locks
-- Good: Consistent ordering (transfer 100 from :from_id to :to_id)-- Lock both rows in ascending id order first, then apply the debit/creditSELECT id FROM accounts WHERE id IN (:from_id, :to_id) ORDER BY id FOR UPDATE;UPDATE accounts SET balance = balance - 100 WHERE id = :from_id;UPDATE accounts SET balance = balance + 100 WHERE id = :to_id;
Why not LEAST/GREATEST in the UPDATEs: that always debits the lower id, so a transfer from 2 to 1 would move money the wrong way. Order the locking, not the business logic.
2. Timeout-Based Prevention
Lock Timeout: Set maximum wait time for locks
Abort on Timeout: Assume deadlock if timeout exceeded
Trade-off: May abort legitimate waits
3. Wait-Die Protocol
Age-Based: Older transactions wait, younger die
Preemption: Younger transactions abort when conflict
Restart: Aborted transactions restart with same timestamp
4. Wound-Wait Protocol
Age-Based: Older transactions preempt younger
Wound: Older forces younger to abort
Wait: Younger waits for older
Deadlock Avoidance
1. Two-Phase Locking with Ordering
Acquire Phase: Get all locks before any operation (this is conservative 2PL; plain 2PL only requires no new lock after the first release, and can still deadlock)
Release Phase: Release all locks after commit
Ordering: Acquire locks in predetermined order
2. Reduce Transaction Scope
Shorter Transactions: Minimize lock hold time
Specific Operations: Avoid unnecessary locks
Quick Commits: Reduce probability of conflicts
3. Application Design Patterns
Retry Logic: Implement exponential backoff
Lock Granularity: Use appropriate lock levels
Access Patterns: Design to minimize conflicts
Performance Impact
Detection Overhead
CPU Cost: Cycle detection algorithms
Memory Usage: Wait-for graph storage
Frequency Trade-off: More frequent = higher overhead, faster detection
Resolution Cost
Rollback Work: Undoing aborted transaction
Retry Overhead: Re-executing failed operations
Lock Thrashing: Repeated deadlocks in same area
Monitoring and Troubleshooting
Key Metrics
Deadlock Frequency: Number of deadlocks per time period
Victim Selection: Which transactions get aborted
Wait Times: Average lock wait duration
Hot Spots: Tables/rows with frequent deadlocks
Database-Specific Commands
-- PostgreSQL: View current locksSELECT * FROM pg_locks;-- MySQL: Show current deadlock infoSHOW ENGINE INNODB STATUS;-- SQL Server: Deadlock graph in extended eventsSELECT * FROM sys.dm_exec_requests WHERE blocking_session_id > 0;
Troubleshooting Steps
Identify Patterns: Which operations cause deadlocks
Analyze Queries: Look for resource ordering issues
Review Indexes: Check for index-related conflicts
Optimize Transactions: Reduce scope and duration
Best Practices
Application Development
Consistent Ordering: Always access resources in same order