Back

    Locking, Deadlocks & High-Concurrency Patterns

    Master row locks, table locks, deadlock prevention, and optimistic locking for scalable applications.

    ๐ŸŽฏ What You'll Learn

    • PostgreSQL's lock hierarchy from ACCESS SHARE to ACCESS EXCLUSIVE
    • Row-level locking: FOR UPDATE, FOR SHARE, SKIP LOCKED, NOWAIT
    • What causes deadlocks and how to prevent them
    • Monitoring and detecting lock contention in production
    • Optimistic locking with version numbers for web applications

    ๐Ÿ” Lock Types โ€” The Hierarchy

    Think of locks like building access levels: some let everyone in (ACCESS SHARE for reads), while others clear the entire building (ACCESS EXCLUSIVE for schema changes). Understanding which operations take which locks prevents surprises in production.

    Lock Types

    PostgreSQL's lock hierarchy and monitoring

    Try it Yourself ยป
    SQL
    -- PostgreSQL Lock Types (from weakest to strongest)
    
    -- 1. ACCESS SHARE โ€” acquired by SELECT
    -- Doesn't block anything except ACCESS EXCLUSIVE
    SELECT * FROM employees;  -- takes ACCESS SHARE lock
    
    -- 2. ROW SHARE โ€” acquired by SELECT ... FOR UPDATE/SHARE
    SELECT * FROM accounts WHERE id = 1 FOR UPDATE;
    -- Locks this specific row so no one else can modify it
    
    -- 3. ROW EXCLUSIVE โ€” acquired by INSERT, UPDATE, DELETE
    UPDATE employees SET salary = 90000 WHERE id = 5;
    -- Locks only the affected rows,
    ...

    ๐Ÿ”’ Row-Level Locking

    Row locks are the surgical tools of concurrency โ€” they lock only the rows you need, leaving the rest of the table accessible. SKIP LOCKED is a game-changer for job queues.

    ๐Ÿ’ก Pro Tip โ€” SKIP LOCKED for Job Queues

    FOR UPDATE SKIP LOCKED turns a regular table into a high-performance job queue. Multiple workers grab different unlocked rows simultaneously โ€” no waiting, no contention, no external queue system needed.

    Row Locking Strategies

    FOR UPDATE, FOR SHARE, SKIP LOCKED, and NOWAIT

    Try it Yourself ยป
    SQL
    -- Row-level locking strategies
    
    -- FOR UPDATE: exclusive lock (I will modify this row)
    BEGIN;
    SELECT * FROM inventory
    WHERE product_id = 100
    FOR UPDATE;
    -- Now this row is locked until COMMIT/ROLLBACK
    -- Other sessions trying FOR UPDATE will WAIT
    UPDATE inventory SET quantity = quantity - 1
    WHERE product_id = 100;
    COMMIT;
    
    -- FOR SHARE: shared lock (I'm reading, don't change it)
    BEGIN;
    SELECT * FROM products
    WHERE id = 100
    FOR SHARE;
    -- Other FOR SHARE allowed, but FOR UPDATE blocked
    COMMIT;
    
    -
    ...

    โ˜ ๏ธ Deadlocks โ€” The Deadly Embrace

    A deadlock is like two people in a narrow hallway โ€” each waiting for the other to move. The database detects this and kills one transaction. Prevention is simple: always lock resources in the same order.

    โš ๏ธ Common Mistake

    Locking rows in different orders across different code paths. If function A locks row 1 then row 2, and function B locks row 2 then row 1 โ€” deadlock. Always sort IDs before locking.

    Deadlock Prevention

    Why deadlocks happen and how to prevent them

    Try it Yourself ยป
    SQL
    -- DEADLOCK: two transactions each waiting for the other
    
    -- Session A:                    -- Session B:
    -- BEGIN;                        -- BEGIN;
    -- UPDATE accounts               -- UPDATE accounts
    --   SET bal = bal - 100          --   SET bal = bal - 50
    --   WHERE id = 1;  โ† locks 1   --   WHERE id = 2;  โ† locks 2
    --
    -- UPDATE accounts               -- UPDATE accounts
    --   SET bal = bal + 100          --   SET bal = bal + 50
    --   WHERE id = 2;  โ† WAITS     --   WHERE id = 1;  โ† WAITS
    --     
    ...

    ๐Ÿ” Detecting Lock Issues

    In production, lock contention shows up as slow queries and timeouts. These diagnostic queries help you find the culprit.

    Lock Monitoring

    Find blocked queries and long-running transactions

    Try it Yourself ยป
    SQL
    -- Detecting and monitoring lock issues
    
    -- 1. Find blocked queries right now
    SELECT blocked.pid AS blocked_pid,
           blocked.query AS blocked_query,
           blocking.pid AS blocking_pid,
           blocking.query AS blocking_query,
           NOW() - blocked.query_start AS wait_duration
    FROM pg_stat_activity blocked
    JOIN pg_locks bl ON blocked.pid = bl.pid AND NOT bl.granted
    JOIN pg_locks gl ON bl.relation = gl.relation
        AND bl.locktype = gl.locktype AND gl.granted
    JOIN pg_stat_activity blocking ON
    ...

    ๐ŸŽฏ Optimistic Locking

    For web applications where users edit data over minutes (not milliseconds), holding database locks is impractical. Optimistic locking uses a version number to detect conflicts at save time.

    Optimistic Locking Pattern

    Version-based conflict detection for web apps

    Try it Yourself ยป
    SQL
    -- Optimistic Locking: no database locks, use version numbers
    -- Best for: web apps where lock duration is unpredictable
    
    -- Table has a version column
    CREATE TABLE documents (
        id INT PRIMARY KEY,
        title VARCHAR(200),
        content TEXT,
        version INT DEFAULT 1,
        updated_at TIMESTAMP DEFAULT NOW()
    );
    
    -- Step 1: Read the document (no lock!)
    SELECT id, title, content, version
    FROM documents WHERE id = 42;
    -- Returns: version = 5
    
    -- Step 2: User edits in the browser (minutes pass...)
    
    -
    ...

    ๐Ÿ“‹ Quick Reference

    StrategyUse When
    FOR UPDATEShort transactions, immediate writes
    SKIP LOCKEDJob queues, parallel workers
    NOWAITFail-fast instead of waiting
    Optimistic lockWeb apps, long user sessions
    Consistent orderDeadlock prevention

    ๐ŸŽ‰ Lesson Complete!

    You now understand locking mechanics, deadlock prevention, and optimistic concurrency. Next, learn about table partitioning for massive datasets!

    Sign up for free to track which lessons you've completed and get learning reminders.

    Previous

    Cookie & Privacy Settings

    We use cookies to improve your experience, analyze traffic, and show personalized ads. You can manage your preferences below.

    By clicking "Accept All", you consent to our use of cookies for analytics and personalized advertising. You can customize your preferences or reject non-essential cookies.

    Privacy Policy โ€ข Terms of Service