Fill the blank
Make the increment safe without explicit locks.
CREATE TABLE counters (id int PRIMARY KEY, n int NOT NULL);
INSERT INTO counters VALUES (1, 10);
UPDATE counters
SET n = ____
WHERE id = 1;
SELECT n FROM counters;Hint 1 of 1
Let the database read and write in one step.
Choose an answer, then open Show answer below to check it.
Run on PostgreSQL 17.11 (two sessions)
Text version
READ COMMITTED:
- A: SELECT n FROM counters WHERE id = 1 (10)
- B: SELECT n FROM counters WHERE id = 1 (10)
- A: UPDATE counters SET n = 11 WHERE id = 1 (app computed 11)
- A: COMMIT (ok)
- B: UPDATE counters SET n = 11 WHERE id = 1 (overwrites A, then COMMIT ok)
REPEATABLE READ:
- A: SELECT n FROM counters WHERE id = 1 (10)
- B: SELECT n FROM counters WHERE id = 1 (10)
- A: UPDATE counters SET n = 11 WHERE id = 1 (app computed 11)
- A: COMMIT (ok)
- B: UPDATE counters SET n = 11 WHERE id = 1 (ERROR 40001, retry)
SERIALIZABLE:
- A: SELECT n FROM counters WHERE id = 1 (10)
- B: SELECT n FROM counters WHERE id = 1 (10)
- A: UPDATE counters SET n = 11 WHERE id = 1 (app computed 11)
- A: COMMIT (ok)
- B: UPDATE counters SET n = 11 WHERE id = 1 (ERROR 40001, retry)
| Level | Result | n |
|---|---|---|
| READ COMMITTED | ✕ Happens | 11 |
| REPEATABLE READ | ↻ 40001, retry | 11 |
| SERIALIZABLE | ↻ 40001, retry | 11 |
Show answer
Answer: A n + 1
Correct. The database computes it from the newest committed value, so concurrent increments don't overwrite each other.
SET n = n + 1 is evaluated by the database against the latest committed row, under the row lock the UPDATE takes. A second concurrent increment waits and then adds to 11, not to the stale 10.
Why not the others?
- B
11. A value computed in the app is exactly the lost-update bug. - C
(SELECT n FROM counters WHERE id = 1) + 1. A subquery reads a snapshot and can lose updates again under concurrency. - D
DEFAULT. Resets the column; it doesn't increment it.