# 6.3.1 The Iron Padlock (Heavyweight Locks)

When reading the Maitre D's Service Receipt (`pg_stat_activity`), seeing an I/O wait simply means the database is slow. But seeing a **Lock Wait** means the database is actively paralyzed by its own citizens.
This is the world of **Heavyweight Locks**—the Iron Padlocks of the Elephant Cafe.
These locks exist for one reason: Data Integrity. If Elephant A is tearing down a shelf to rebuild it, Elephant B cannot be allowed to stand on that shelf looking for soup. Postgres enforces this safety with brute force.
## The Three Padlocks
When you see a `wait_event_type: Lock`, the Chef has encountered a closed door and must wait in a polite, single-file line until the door opens. The specific `wait_event` tells you *what* kind of door is locked:
### 1. `relation` (The Cabinet Lock)
This specifies that an entire table (a relation) is locked.
This is usually caused by heavy Data Definition Language (DDL) commands. If someone runs `ALTER TABLE ingredients ADD COLUMN spicy BOOLEAN;`, they must throw a giant padlock over the entire "ingredients" cabinet.
Any `SELECT`, `UPDATE`, or `INSERT` query that needs that cabinet will stop in its tracks and throw a `Lock:relation` wait until the `ALTER` is finished.
### 2. `tuple` (The Suitcase Lock)
This specifies that a single, extremely specific row (a tuple) is locked.
This occurs during high-concurrency "hot row" updates. If 1,000 customers try to buy the exact same concert ticket at the exact same millisecond, 999 of the chefs will throw a `Lock:tuple` wait while the first chef processes the payment and writes the update.
### 3. `transactionid` (The Pinky-Swear Wait)
This is the most common and complex of the lock waits. As detailed in **[[Chapter 4/4.4 - The Pinky Swear (Transactions)|Chapter 4]]**, every multi-step transaction is a promise that might be broken (rolled back).
If Chef A begins a transaction and touches Row X, he holds the "transaction ID" lock on that row.
If Chef B wants to touch Row X, he doesn't just wait for the row to be free—he waits for Chef A's *entire transaction* to explicitly `COMMIT` or `ROLLBACK`. The database is saying, "I can't let you see this row until the other guy officially guarantees he's finalized his recipe."
> [!info] Diagnostics: The Iron Padlock (Locks)
> Are your elephants stuck at a structural blockade? Dive into the **[[Workloads/Lock/_Lock|Heavyweight Lock Library]]** to identify the exact queues of table, transaction, and relation-level stalls.
## The Deadlock Detector
Locks are polite, which makes them dangerous. If Chef A locks the Onion bucket and waits for the Tomato bucket, while Chef B locks the Tomato bucket and waits for the Onion bucket, they will politely wait in silence until the heat death of the universe.
This creates the legendary **Deadlock**. To solve it, a background goose (the deadlock detector) occasionally flies over the cafe, honks loudly, and murders one of the chefs (aborts their transaction) so the other can proceed. If you see Deadlock errors, your app is locking tables in inconsistent order!
---
| ← Previous | ↑ Table of Contents | Next → |
| :--- | :---: | ---: |
| [[Chapter 6/6.3 - The Narrow Bridge (Locks & Latches)\|6.3 The Narrow Bridge (Locks & Latches)]] | [[Learn You a Postgres for Great Good\|Home]] | [[Chapter 6/6.3.2 - The Shoulder Nudge (LWLocks & BufferPins)\|6.3.2 The Shoulder Nudge (LWLocks & BufferPins)]] |