1. Introduction
Deadlocks are one of the most painful performance problems in OLTP systems. They occur when two (or more) sessions block each other in a circular wait—each holding locks the other needs.
Row-versioning–based isolation levels in SQL Server (like READ COMMITTED SNAPSHOT (RCSI) and SNAPSHOT) dramatically reduce deadlocks by removing many reader–writer conflicts without lowering consistency guarantees.
This article is a fully practical guide covering:
Why deadlocks occur
What row versioning is
RCSI vs SNAPSHOT
How they reduce deadlocks
How to enable them safely
Real-world patterns, scripts, and troubleshooting
2. Why Deadlocks Happen (Quick Refresher)
2.1 A typical deadlock pattern
Example:
Session A:
UPDATE Orders SET Status = 'Paid' WHERE Id = 1;
Session B:
SELECT * FROM Orders WHERE Id = 1;
UPDATE Payments SET Confirmed = 1 WHERE OrderId = 1;
Session A holds a write lock, B holds a read lock, and next each wants the other’s lock.
SQL Server detects the cycle and kills one.
2.2 Common causes
Long-running read queries blocking writes
Writes blocking reads
Poor indexing → forced table scans → many locks acquired
Serializable isolation used incorrectly
Application patterns causing lock escalation
Wide updates touching many rows
Most OLTP deadlocks are caused by reader–writer blocking, which row versioning eliminates.
3. What is Row Versioning?
SQL Server stores old versions of modified rows in TempDB.
Readers can access these consistent snapshots without blocking writers.
3.1 How versioning works
When a row is updated:
Old version goes to TempDB version store
Writers continue normally
Readers (in RCSI/SNAPSHOT modes) read the previous version, not the locked row
Thus:
Reads never wait for writes
Writes never wait for reads
This eliminates 60–90% of deadlocks in real-world systems.
4. Row-Versioning Isolation Levels
There are two major options:
4.1 READ COMMITTED SNAPSHOT (RCSI)
Makes standard
READ COMMITTEDbehave like snapshot readsAutomatically uses row versions for all SELECT statements
Does NOT require explicit BEGIN TRAN…SNAPSHOT
Enable:
ALTER DATABASE YourDB SET READ_COMMITTED_SNAPSHOT ON;
Effects:
No reader/writer blocking
Writers still block writers
No application change needed
Minimal behavior shift from default RC
Most recommended for OLTP systems.
4.2 SNAPSHOT Isolation
Explicit snapshot transactions:
ALTER DATABASE YourDB SET ALLOW_SNAPSHOT_ISOLATION ON;
Application must request SNAPSHOT:
SET TRANSACTION ISOLATION LEVEL SNAPSHOT;
BEGIN TRAN;
SELECT ...;
UPDATE ...;
COMMIT;
Effects:
No read locks
No read/write blocking
Even write-write conflicts are detected at commit time (update conflict error)
Best for:
Long-running read transactions
Reporting queries
ETL reads without blocking production
5. How Row Versioning Reduces Deadlocks
✓ Eliminates reader–writer deadlocks
Under normal READ COMMITTED:
SELECT acquires share locks
UPDATE acquires exclusive locks
If both access same row(s), deadlock risk is high

Join the conversation! Your thoughts help the community grow.