Row-level locking (FOR UPDATE, FOR SHARE) in PostgreSQL - Time & Space Complexity
Start learning this pattern below
Jump into concepts and practice - no test required
When using row-level locking in a database, it is important to understand how the time to lock rows grows as the number of rows increases.
We want to know how the locking operation scales when more rows are involved.
Analyze the time complexity of the following PostgreSQL query using row-level locking.
SELECT * FROM orders
WHERE status = 'pending'
FOR UPDATE;
This query selects all rows with status 'pending' and locks them to prevent other transactions from modifying them until this transaction finishes.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Scanning rows that match the condition and locking each one.
- How many times: Once for each matching row in the table.
As the number of rows with status 'pending' grows, the database must lock more rows one by one.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | Locks 10 rows |
| 100 | Locks 100 rows |
| 1000 | Locks 1000 rows |
Pattern observation: The number of locking operations grows directly with the number of rows locked.
Time Complexity: O(n)
This means the time to lock rows grows linearly with the number of rows matched and locked.
[X] Wrong: "Locking rows happens all at once, so time does not depend on how many rows are locked."
[OK] Correct: Each row must be locked individually, so more rows mean more work and more time.
Understanding how row-level locking scales helps you reason about database performance and concurrency control in real applications.
"What if we added an index on the status column? How would the time complexity of locking rows change?"
Practice
FOR UPDATE clause do in a PostgreSQL query?Solution
Step 1: Understand the purpose of
TheFOR UPDATEFOR UPDATEclause locks the rows returned by the query to prevent other transactions from modifying them.Step 2: Compare with other locking types
UnlikeFOR SHARE, which allows reading but prevents writing,FOR UPDATEblocks other transactions from modifying the locked rows until the current transaction ends.Final Answer:
Locks selected rows to prevent other transactions from modifying them until the current transaction ends. -> Option AQuick Check:
FOR UPDATE= exclusive row lock [OK]
- Confusing FOR UPDATE with table-level locks
- Thinking FOR UPDATE allows other writes
- Mixing FOR UPDATE with FOR SHARE behavior
Solution
Step 1: Identify the clause for read locks
In PostgreSQL,FOR SHAREis used to lock rows for reading, allowing other transactions to read but not modify.Step 2: Check syntax correctness
Options B and C are invalid syntax. SELECT * FROM orders FOR UPDATE; locks rows for writing, not reading.Final Answer:
SELECT * FROM orders FOR SHARE; -> Option BQuick Check:
Read lock = FOR SHARE [OK]
- Using FOR UPDATE instead of FOR SHARE for read locks
- Using non-existent LOCK ROW or WITH LOCK syntax
- Confusing table-level locks with row-level locks
-- Transaction 1
BEGIN;
SELECT * FROM products WHERE id = 10 FOR UPDATE;
-- Transaction 2
BEGIN;
SELECT * FROM products WHERE id = 10 FOR SHARE;What will happen when Transaction 2 tries to execute its SELECT statement?
Solution
Step 1: Understand locking conflict between FOR UPDATE and FOR SHARE
AFOR UPDATElock is exclusive and blocks other transactions from acquiring conflicting locks, includingFOR SHARE.Step 2: Analyze Transaction 2 behavior
Transaction 2'sFOR SHARElock request conflicts with Transaction 1'sFOR UPDATElock, so it must wait until Transaction 1 finishes.Final Answer:
Transaction 2 will wait until Transaction 1 commits or rolls back before proceeding. -> Option CQuick Check:
FOR UPDATE blocks FOR SHARE until commit [OK]
- Assuming FOR SHARE can proceed during FOR UPDATE lock
- Expecting deadlock without waiting
- Ignoring lock conflicts between FOR UPDATE and FOR SHARE
SELECT * FROM customers FOR SHARE;But you want to prevent other transactions from modifying these rows. What is wrong and how to fix it?
Solution
Step 1: Identify the locking behavior of FOR SHARE
FOR SHARElocks rows to allow reading but does not prevent other transactions from modifying them.Step 2: Choose correct clause to prevent modifications
To block other transactions from modifying rows, useFOR UPDATEinstead ofFOR SHARE.Final Answer:
FOR SHARE locks rows only for reading; replace it with FOR UPDATE to lock for writing. -> Option DQuick Check:
Prevent writes = use FOR UPDATE [OK]
- Thinking FOR SHARE blocks writes
- Using LOCK TABLE unnecessarily
- Missing WHERE clause but unrelated to locking type
Solution
Step 1: Understand the locking levels
FOR UPDATElocks rows exclusively, blocking writes by others until commit, but does not block reads.Step 2: Compare with other lock types
FOR SHAREandFOR KEY SHAREallow reads;FOR NO KEY UPDATEis less restrictive and allows some concurrent updates.Step 3: Choose the strictest lock to block writes
OnlyFOR UPDATEfully blocks other transactions from modifying the rows, but it does not block reads.Final Answer:
SELECT * FROM table_name FOR UPDATE; -> Option AQuick Check:
Block writes = FOR UPDATE [OK]
- Choosing FOR SHARE or KEY SHARE which allow writes
- Using NO KEY UPDATE which is less strict
- Not understanding lock levels and their effects
