Question presented to candidate: "Two requests try to update the same row at the same time. What is the difference between optimistic and pessimistic locking for handling that, how would you implement each, and when would you pick one over the other?"
What a strong answer should cover:
- The problem both solve: the lost update (read, modify, write by two transactions; one write silently overwrites the other)
- Pessimistic: take a lock before reading (
SELECT ... FOR UPDATE); others wait until commit; risks are waiting, deadlocks and locks held by slow clients - Optimistic: read a version (or ETag), write with
WHERE version = :v; if zero rows changed, someone else won, so re-read and retry; risks are wasted work and retry storms under contention - The deciding factor is contention: rare conflicts favour optimistic (no waiting, no lock held during think time); hot rows favour pessimistic (no wasted retries)
- Neighbours worth naming: a single atomic
UPDATE ... SET n = n - 1 WHERE n > 0that needs neither,NOWAIT/SKIP LOCKED, HTTPIf-Matchreturning 412, serializable isolation that aborts and must be retried
Clarifying questions expected:
- How often do two writers touch the same row, and how long is the gap between reading and writing (milliseconds of code, or minutes of a human editing a form)?
- Is the lock inside one database, or across services (which needs a distributed lock with fencing)?
Code / implementation expected: Optional โ the SQL for both patterns, or a simulation comparing them under low and high contention; the example does the simulation.