2

Have tried researching the existing questions, but did not find posts with a definitive answer.

What we want to implement is to atomically update the value of two rows in one postgres table. we would like to implement logic similar to the blow. We can capture the whole logic in one transaction and set the transaction level to serializable to guarantee atomicity. My understand is that that will have the database to lock the whole table, and reduce concurrency and throughput. What is the best practice for increasing concurrency while gauaranteeing atomicity?

 create table accounts (
     id  int,
     remain double
}

remain = account1.remain
if val <= remain:   
    account1.remain = account1.remain - val
    account2.remain = account2.remain + val
1
  • 1
    serializable will not "lock the whole table" Commented Jul 22, 2018 at 7:34

1 Answer 1

1

The simplest way is to use a single UPDATE statement, because each individual SQL statement is always atomic.

An example - let say that:

account1_id = 222
account2_id = 333
val = 567

then the update might look like this:

UPDATE accounts
SET remain = remain + 567 * CASE id
         WHEN 222 THEN -1
         WHEN 333 THEN 1
    END
WHERE id IN ( 222,333 )
  AND 567 >= (
     SELECT remain FROM accounts
     WHERE id = 222
);
COMMIT;

this statement will lock only two rows 222 and 333 (which must be locked in order to be updated), leaving the rest of rows in the table in unlocked state, so the concurency will be the highest.

Sign up to request clarification or add additional context in comments.

1 Comment

thanks for the answer! i think that read committed isolation should be sufficient for this query. is my understanding correct?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.