PromptHub
Database Advanced 14 views

Deadlock Found

Two or more database transactions are blocking each other, creating a circular wait.

Explanation

Deadlock found occurs when two or more transactions are waiting for each other to release locks, creating a circular dependency that the database cannot resolve. For example, Transaction A locks Row 1 and waits for Row 2, while Transaction B locks Row 2 and waits for Row 1. The database detects this situation and kills one transaction (the deadlock victim) to allow the other to proceed. This is common in applications with concurrent database operations.

Common Causes

  • Transactions acquiring locks in different order
  • Long-running transactions holding locks
  • Missing indexes causing table-level locks
  • Concurrent write operations on same rows
  • Lock escalation from row to table level

Solution

Ensure all transactions acquire locks in the same order to prevent circular waits. Keep transactions as short as possible to minimize lock duration. Use optimistic locking instead of pessimistic locking where appropriate. Implement retry logic for deadlock victims. Add proper indexes to reduce lock scope. Use SELECT ... FOR UPDATE carefully and only when necessary. Monitor deadlock logs to identify patterns. Consider using queue-based processing for operations that frequently deadlock.

Code Example

// Transaction A and B cause deadlock
// Transaction A:
DB::beginTransaction();
DB::table('accounts')->where('id', 1)->lockForUpdate();
DB::table('accounts')->where('id', 2)->lockForUpdate(); // waits!

// Transaction B (concurrent):
DB::beginTransaction();
DB::table('accounts')->where('id', 2)->lockForUpdate();
DB::table('accounts')->where('id', 1)->lockForUpdate(); // waits!
// DEADLOCK!

// Fix: always lock in same order
DB::beginTransaction();
DB::table('accounts')->where('id', 1)->lockForUpdate();
DB::table('accounts')->where('id', 2)->lockForUpdate();
// Transaction B does same order

// Retry logic
function executeWithRetry(callable $fn, int $retries = 3) {
    for ($i = 0; $i < $retries; $i++) {
        try {
            return $fn();
        } catch (QueryException $e) {
            if ($e->errorInfo[1] == 1213 && $i < $retries - 1) {
                usleep(100000); // 100ms delay
                continue;
            }
            throw $e;
        }
    }
}

Error Information

Language

php

Difficulty

Advanced

Views

14

Related Errors