Lesson 8 of 8

The Lock Manager: How PostgreSQL Coordinates Concurrent Access

Applies to PostgreSQL 13–17 Last reviewed May 2026 Grounded in source

The one thing to understand first

MVCC removes the need to lock for ordinary reads, but PostgreSQL still needs locks to coordinate DDL, conflicting writes, and access to shared memory structures. There are three distinct mechanisms, each for a different purpose:

  • Heavyweight locks (lock manager, lock.c) — table and row-level locks visible in pg_locks.
  • Lightweight locks (LWLocks) — short-duration locks protecting in-memory structures like buffer headers and the WAL.
  • Spinlocks — the lowest level, a few instructions guarding an LWLock’s own state.

Readers and writers do not block each other — but DDL blocks everyone. The whole art of safe operations comes from one fact in the conflict table: ACCESS EXCLUSIVE (taken by most ALTER TABLE) collides with even a plain SELECT, so a careless schema change can freeze the entire application.

Heavyweight lock modes and the conflict table

Table-level locks come in eight modes, from ACCESS SHARE (taken by SELECT) to ACCESS EXCLUSIVE (taken by DROP, most ALTER TABLE, VACUUM FULL). The rules for which modes can coexist live in a static conflict table in src/backend/storage/lmgr/lock.c. The key facts:

This is a Pro lesson

Get every Learning Pathway and cookbook recipe — grounded in PostgreSQL source code, with diagnostics, fixes, and prevention for each topic.

Continue this lesson to learn:

  • Row-level locks live in the tuple, not the lock table
  • Multixacts: many lockers, one row
  • Deadlock detection
  • LWLocks: the in-memory workhorses
  • Layer 3 — Watch it happen on your own database
  • Layer 4 — The levers this hands you
  • All 36 Learning Pathway lessons
  • 170+ cookbook recipes
  • Source-grounded diagnostics & fixes

Secure checkout Cancel anytime Source-grounded

Was this helpful?

← Back to 01 — Foundations: PostgreSQL Internals 101