|
|
|
|
|
by erhaetherth
801 days ago
|
|
I'm having trouble with the example given. If `UPDATE player SET level = 'AA' WHERE team = 'Gophers';` is executed before the player swap, then why should "Stonebreaker" be upgraded to "AA"? I'd be pretty mad at my database if I sent those 2 queries in sequence and my DB decided to re-order them. The sleep actually really complicates things here. I understand some queries run slower than others and the sleep is a useful tool to artificially slow things down, but now I don't know I don't know if I should interpret that as one command or two. If `WITH sleep AS (SELECT pg_sleep(5))
UPDATE player SET level = 'AA' FROM sleep WHERE team = 'Gophers';` is atomic then I'd expect it to put a lock on the 3 Gophers (which doesn't include Stonebreaker), wait the 5 seconds and then complete the update. The player swap would be blocked for those 5 seconds because it touches a row that's being updated. |
|
Here's a full timeline in PG (U1 for first update, U2 for second update):
0. U1 begins executing, establishes read snapshot, starts pg_sleep(5).
1. U2 runs to completion.
2. U1 wakes up after 5 sec, scans `player` using snapshot from step 0.
3. U1 filters `team = Gophers`, gets 4, 5, 6.
4. U1 locks 4, 5, 6.
5. U1 performs EvalQualPlan: re-scans latest version of those locked rows, which sees U2's write to 4 but not to 3.
6. U1 performs EvalQualPlan: re-filters those locked rows using latest version, gets 5, 6.
7. U1 writes new versions.
CRDB is easier to reason about: after U1 wakes up from the sleep, it sees that it conflicts with U2 and simply retries the entire statement.