Deadlocks are one of the most feared issues in SQL Server production environments. They donβt always appear in development, but when they hit production, they can freeze applications, fail transactions, and frustrate users.
This blog explains what deadlocks are, why they occur, and how to prevent them effectively.
1οΈβ£ What Is a Deadlock in SQL Server?
A deadlock occurs when:
- Session A locks Resource 1 and waits for Resource 2
- Session B locks Resource 2 and waits for Resource 1
π SQL Server resolves this by killing one session (deadlock victim).
2οΈβ£ Deadlock Error Message
β Error Message
Msg 1205, Level 13, State 51
Transaction (Process ID xx) was deadlocked on lock resources with another process and has been chosen as the deadlock victim.
3οΈβ£ Simple Deadlock Example
Session 1
BEGIN TRAN;
UPDATE Accounts SET Balance = Balance - 100 WHERE Id = 1;
-- waits
UPDATE Accounts SET Balance = Balance + 100 WHERE Id = 2;
COMMIT;
Session 2
BEGIN TRAN;
UPDATE Accounts SET Balance = Balance - 50 WHERE Id = 2;
-- waits
UPDATE Accounts SET Balance = Balance + 50 WHERE Id = 1;
COMMIT;
π Both sessions wait on each other β deadlock
4οΈβ£ Common Causes of Deadlocks
β Different order of table access
β Long-running transactions
β Missing indexes
β Cursor usage
β User-defined functions inside transactions
5οΈβ£ How SQL Server Chooses Deadlock Victim
SQL Server selects:
- Transaction with the lowest cost
- Transaction with the lowest rollback impact
The killed session receives error 1205.
6οΈβ£ How to Detect Deadlocks
π Method 1: SQL Server Error Log
EXEC xp_readerrorlog;
π Method 2: Extended Events (Recommended)
Use:
xml_deadlock_report
π Method 3: SQL Server Profiler (Old)
Not recommended for production.
7οΈβ£ How to Prevent Deadlocks
β 1. Access Objects in Same Order
Always update tables in a consistent order.
β 2. Keep Transactions Short
β Avoid user input inside transactions
β Avoid delays
β 3. Use Proper Indexes
Indexes reduce lock duration and scope.
β 4. Use SET DEADLOCK_PRIORITY
SET DEADLOCK_PRIORITY LOW;
Lower priority session will be killed first.
β 5. Use Snapshot Isolation (When Possible)
ALTER DATABASE MyDB
SET READ_COMMITTED_SNAPSHOT ON;
Reduces read locks.
8οΈβ£ Handling Deadlocks in Stored Procedures
β Retry Logic Example
DECLARE @Retry INT = 3;
WHILE @Retry > 0
BEGIN
BEGIN TRY
EXEC dbo.TransferAmount;
BREAK;
END TRY
BEGIN CATCH
IF ERROR_NUMBER() = 1205
SET @Retry = @Retry - 1;
ELSE
THROW;
END CATCH
END
9οΈβ£ Deadlocks vs Blocking
| Blocking | Deadlock |
|---|---|
| Temporary wait | Permanent wait |
| Eventually resolves | One session killed |
| Normal behavior | Error condition |
π Deadlock Best Practices Checklist
β Use consistent object order
β Keep transactions short
β Avoid cursors
β Index foreign keys
β Handle error 1205
β Monitor deadlocks
π Deadlock-Safe Stored Procedure Template
CREATE PROCEDURE dbo.SafeTransfer
@FromId INT,
@ToId INT,
@Amount DECIMAL(10,2)
AS
BEGIN
SET NOCOUNT ON;
BEGIN TRY
BEGIN TRANSACTION;
UPDATE Accounts SET Balance = Balance - @Amount WHERE Id = @FromId;
UPDATE Accounts SET Balance = Balance + @Amount WHERE Id = @ToId;
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0
ROLLBACK TRANSACTION;
THROW;
END CATCH
END
βοΈ Conclusion
Deadlocks are not bugs; they are design problems. With correct transaction design, indexing, and error handling, most deadlocks can be completely avoided.
Understanding deadlocks makes you production-ready as a SQL Server developer.
