News for hackers. Stuff that matters.
Re:PostgreSQL anti-patterns: read-modify-write cycles (2014) by buro9 on Wednesday December 21, 2016 @03:53AM (#13227729)
Hmm.

Am I the only one who would consider a CTE for this, selecting the initial balance and the proposed balance minus amount in the CTE, testing it in the query following the CTE and potentially applying it, and then returning the original and new balance to the application. If both are the same then the update was not applied (not enough balance), and if different the update was applied (enough balance for the withdrawal).

This way it all occurs within a single transaction, even though it is several logical steps, and is simple to reason about.

Re:PostgreSQL anti-patterns: read-modify-write cycles (2014) by glogla on Wednesday December 21, 2016 @04:08AM (#13227784)
That's the optimistic way - do the transaction, return result and if the result doesn't pass the validation, rollback.

In postgres, you don't really need to do CTE - UPDATE can return the new row if you add RETURNING * so you can just do the update and look at result.

In Oracle (and what we did in actual bank) was pl/sql procedure that did

- select for update - do the validation - apply the transfer, or return error. - let the application rollback or commit

This is hard to do without procedural language - you can work with CTEs and functions, but SQL is great at dataflow and bad at control flow, and you either drop to procedural language in database, or have the application do the actual logic.

Re:PostgreSQL anti-patterns: read-modify-write cycles (2014) by bpicolo on Wednesday December 21, 2016 @10:58AM (#13230066)
CTEs are still vulnerable to race conditions afaik, plus postgres does a poor job of optimizing them performance wise (that is, it doesn't) http://blog.2ndquadrant.com/postgresql-ctes-are-optimization...
Re:PostgreSQL anti-patterns: read-modify-write cycles (2014) by eveningcoffee on Wednesday December 21, 2016 @09:11AM (#13229174)
In principle if you want to do the (withdrawal) balance check then you can incorporate it into a single query

  UPDATE balance SET balance = balance - 100
  WHERE user_id = 1 and balance >= 100;
Only problem is that you now actually do not know if the query did not update because of insufficient balance or because lack of user in the database.
Re:PostgreSQL anti-patterns: read-modify-write cycles (2014) by buro9 on Wednesday December 21, 2016 @09:15AM (#13229211)
That is why I prefer the CTE approach.

Query 1 (in CTE): Verify all is correct and the current balance (and whether you have enough balance)

Query 2: Perform update and obtain new balance

Then return a summary showing the starting balance and end balance for the transaction (proof of what, if anything, happened).