Deadlocks are scary.
Suddenly, your application throws this error:
Transaction (Process ID 52) was deadlocked on lock resources with another process
and has been chosen as the deadlock victim.
But hereβs the truth:
π Deadlocks are not bugs.
π Deadlocks are not crashes.
π Deadlocks are SQL Server protecting your data.
Letβs understand them properly.
1οΈβ£ What is a Deadlock?
A deadlock happens when:
- Session A holds Lock 1 and waits for Lock 2
- Session B holds Lock 2 and waits for Lock 1
Neither can proceed.
SQL Server automatically kills one transaction (victim) to resolve it.
In Microsoft SQL Server, this happens instantly.
2οΈβ£ Simple Deadlock Example
Session 1:
BEGIN TRAN;
UPDATE Orders SET Amount = 100 WHERE OrderId = 1;
WAITFOR DELAY '00:00:05';
UPDATE Customers SET Name = 'A' WHERE CustomerId = 1;
COMMIT;
Session 2:
BEGIN TRAN;
UPDATE Customers SET Name = 'B' WHERE CustomerId = 1;
WAITFOR DELAY '00:00:05';
UPDATE Orders SET Amount = 200 WHERE OrderId = 1;
COMMIT;
Boom π₯ Deadlock.
3οΈβ£ Why Deadlocks Happen
β Different table access order
β Long transactions
β Missing indexes
β High isolation level (SERIALIZABLE)
β Large updates
4οΈβ£ Deadlock vs Blocking
| Feature | Blocking | Deadlock |
|---|---|---|
| Waits? | Yes | Yes |
| Automatically resolved? | No | Yes |
| Error thrown? | No | Yes |
Deadlock throws error.
Blocking just waits.
5οΈβ£ Capturing Deadlocks
Option 1: Extended Events (Best Way)
CREATE EVENT SESSION DeadlockMonitor
ON SERVER
ADD EVENT sqlserver.xml_deadlock_report
ADD TARGET package0.event_file;
Option 2:
Check system health session (default).
6οΈβ£ Reading Deadlock Graph
Deadlock graph shows:
β Victim process
β Lock types
β Resources involved
β Execution details
In SSMS, open .xel file and view the graph visually.
7οΈβ£ How SQL Server Chooses Victim
SQL Server picks the transaction with:
- Lower rollback cost
- Or based on DEADLOCK_PRIORITY
Set priority:
SET DEADLOCK_PRIORITY LOW;
Options:
- LOW
- NORMAL
- HIGH
- Numeric (-10 to 10)
8οΈβ£ Fixing Deadlocks β Proven Solutions
β 1. Access Tables in Same Order
Always update tables in consistent order across procedures.
Example:
- First Orders
- Then Customers
Never reverse it.
β 2. Add Proper Indexes
Missing index = longer locks = more deadlocks.
Check execution plans.
β 3. Keep Transactions Short
β Avoid:
BEGIN TRAN
-- user input
-- complex logic
-- delays
COMMIT
β Move logic outside transaction.
β 4. Use READ COMMITTED SNAPSHOT
ALTER DATABASE MyDatabase
SET READ_COMMITTED_SNAPSHOT ON;
Reduces read-write deadlocks significantly.
β 5. Retry Logic in Application
Deadlocks can still happen.
Best practice:
- Catch error 1205
- Retry transaction
Example (pseudo logic):
If deadlock
Retry up to 3 times
9οΈβ£ Real Production Scenario
β Issue
Payment API randomly failing.
π Root Cause
Two stored procedures updating:
- Payments
- Accounts
in opposite order.
β Fix
Standardized table access order.
Deadlocks disappeared.
π Monitoring Deadlocks
SELECT *
FROM sys.dm_tran_locks;
Also monitor:
- Wait stats
- Blocking sessions
- Long-running transactions
1οΈβ£1οΈβ£ Deadlock Prevention Checklist
β Keep transactions short
β Access tables in consistent order
β Use proper indexing
β Avoid unnecessary SERIALIZABLE isolation
β Enable RCSI in high concurrency systems
β Implement retry logic
1οΈβ£2οΈβ£ Important Truth
Deadlocks are normal in high-concurrency systems.
Goal is not to eliminate them completely.
Goal is:
β Minimize
β Detect
β Handle gracefully
βοΈ Conclusion
If you understand deadlocks, you understand:
- Locking
- Isolation
- Concurrency
- Real production behavior
That makes you a serious backend professional πͺ
Your blog series now covers:
β Security
β Query Store
β Isolation Levels
β Deadlocks
