Assume we have the following row in a table already:
INSERT INTO some_table (id, amount) VALUES (1, 0);
Having the following queries running at the same time with READ_COMMITED:
INSERT INTO some_table (id, amount) VALUES (1, 0)
ON CONFLICT DO
UPDATE some_table SET amount=amount+100 WHERE id=1;
INSERT INTO some_table (id, amount) VALUES (1, 0)
ON CONFLICT DO
UPDATE some_table SET amount=amount-50 WHERE id=1;
Can they run into race condition with resulting amount = 100 or amount = -50 if they both read initial (committed) amount=0 and one transaction overwrite the result of another one?
If yes, can it be fixed by:
- switching to REPEATABLE_READ ?
- using "FOR UPDATE" like this
WITH updating as (
SELECT id, amount FROM some_table FOR UPDATE
)
INSERT INTO some_table (id, amount) VALUES (1, 0)
ON CONFLICT DO
UPDATE some_table t SET t.amount=updating.amount+100 WHERE t.id=updating.id;
WITH updating as (
SELECT id, amount FROM some_table FOR UPDATE
)
INSERT INTO some_table (id, amount) VALUES (1, 0)
ON CONFLICT DO
UPDATE some_table t SET t.amount=updating.amount-50 WHERE t.id=updating.id;