SQL Server  

How to Fix Database Deadlocks in SQL Server or MySQL

Introduction

In high-traffic applications, database deadlocks are a common and critical issue that can affect performance, reliability, and user experience. Deadlocks occur when two or more transactions block each other by holding locks on resources that the other transactions need.

If not handled properly, deadlocks can cause transaction failures, slow response times, and system instability.

In this article, we will understand what deadlocks are, why they happen, and how to fix and prevent them in SQL Server and MySQL using simple language and real-world examples.

What is a Database Deadlock?

A deadlock happens when two or more transactions are waiting for each other to release locks, and none of them can proceed.

Example

  • Transaction A locks Row 1

  • Transaction B locks Row 2

  • Transaction A tries to lock Row 2 (blocked)

  • Transaction B tries to lock Row 1 (blocked)

Now both are waiting forever → this is a deadlock.

The database engine detects this situation and automatically kills one transaction to resolve it.

Why Deadlocks Happen

Deadlocks usually occur due to poor query design or improper transaction handling.

Common Causes

  • Transactions accessing resources in different order

  • Long-running transactions

  • Missing indexes causing full table scans

  • High concurrency (many users accessing same data)

Understanding the root cause is the first step to fixing deadlocks.

How SQL Server and MySQL Handle Deadlocks

SQL Server

  • Automatically detects deadlocks

  • Chooses a victim transaction

  • Rolls it back

Error example:

Transaction (Process ID 55) was deadlocked on resources and has been chosen as the deadlock victim.

MySQL

  • Uses InnoDB engine for deadlock detection

  • Rolls back one transaction

Error example:

Deadlock found when trying to get lock; try restarting transaction

How to Detect Deadlocks

SQL Server

Use Extended Events or Query:

SELECT * FROM sys.dm_tran_locks;

You can also enable deadlock graph capture for detailed analysis.

MySQL

SHOW ENGINE INNODB STATUS;

This shows the latest deadlock information.

How to Fix Deadlocks

1. Access Tables in Consistent Order

Always access tables in the same order in all transactions.

Bad:

  • Transaction A → Table1 → Table2

  • Transaction B → Table2 → Table1

Good:

  • Both transactions → Table1 → Table2

This reduces circular waiting.

2. Keep Transactions Short

Long transactions hold locks for a longer time.

Example

Bad:

  • Start transaction

  • Perform multiple operations

  • Delay commit

Good:

  • Perform quick operations

  • Commit immediately

Short transactions reduce lock contention.

3. Use Proper Indexing

Without indexes, database scans entire tables and locks more rows.

Example

CREATE INDEX idx_user_email ON users(email);

This ensures faster lookup and fewer locks.

4. Use Lower Isolation Levels

Higher isolation levels increase locking.

Example

SET TRANSACTION ISOLATION LEVEL READ COMMITTED;

This reduces locking conflicts compared to SERIALIZABLE.

5. Use Row-Level Locking Instead of Table Locks

Ensure your queries use row-level locking instead of locking entire tables.

This improves concurrency and reduces deadlock chances.

6. Handle Deadlocks in Application Code

Deadlocks can still happen, so handle them gracefully.

Example (Retry Logic)

for (let i = 0; i < 3; i++) {
  try {
    await executeTransaction();
    break;
  } catch (err) {
    if (err.code === 'DEADLOCK') {
      continue;
    }
    throw err;
  }
}

Retrying the transaction often resolves temporary deadlocks.

7. Avoid User Interaction Inside Transactions

Do not keep transactions open while waiting for user input.

Bad:

  • Start transaction

  • Wait for user confirmation

Good:

  • Collect input first

  • Then start transaction

8. Break Large Transactions into Smaller Ones

Large transactions increase lock duration.

Solution:

  • Split into smaller batches

This improves performance and reduces deadlocks.

Real-World Example

A financial application experienced frequent deadlocks during peak hours.

Problem:

  • Multiple transactions updating accounts in different order

Solution:

  • Standardized update order

  • Added indexes

  • Reduced transaction time

Result:

  • Deadlocks reduced by 80%

  • System performance improved

Best Practices to Prevent Deadlocks

  • Always access resources in a consistent order

  • Keep transactions short and simple

  • Use proper indexing

  • Monitor and analyze deadlocks regularly

  • Implement retry logic in applications

  • Choose appropriate isolation levels

Summary

Database deadlocks are a common issue in high-concurrency systems like SQL Server and MySQL, but they can be effectively managed with proper design and best practices. By keeping transactions short, using consistent query patterns, applying indexing, and handling deadlocks gracefully in application code, developers can build reliable and high-performance systems that minimize disruptions and maintain smooth operation.