I'm running Postgres12 and confused about the behavior of the serializable transaction level.
Tables:
Events
Managers
Intended behavior (within serialized transaction):
I'm running the following transactions in serializable but not seeing the behavior I am expected (expected the serializable transaction to detect write skew between 2 sessions)
-- session 1:
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE
SELECT count(*) from events WHERE difficulty=2
-- RETURNS 7
-- now start session 2
-- session 2:
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE
SELECT id FROM events WHERE difficulty=2 LIMIT 1;
/*
id
----
4
*/
UPDATE events SET difficulty=1 WHERE id=4;
COMMIT;
now there are only 6 events of difficulty=2
-- back in session 1
-- since we have counted 7 events of difficulty=2 in this session, create a manager
INSERT INTO manager (level) VALUES (2);
COMMIT;
-- Expected write skew to be detected here bc the read event rows have seen updates (only 6 actually)
Unfortunately, our final state is now 6 events of difficulty=2 and a manager of level 2. Why didn't serializable isolation prevent this write skew? What am I misunderstanding about serializable isolation use case? Why are events with difficulty=2 not locked or watched by predicate locking or some isolation mechanism?
Picture for clarity
SERIALIZABLE
means that there is a way to execute the transactions serially (one after the other) so that the effect is the same. In your case, this equivalent serial execution would run session 1 first, then session 2, with the same effect.
You could say that session 1 executes "logically" before session 2.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With