TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

PostgreSQL anti-patterns: read-modify-write cycles (2014)

224 pointsby kornishover 8 years ago

12 comments

rejschaapover 8 years ago
Another solution is to not use update statements at all. Obviously this involves some changes to the tables. And it defers the balance calculation to query time.<p>Analogous to the example from the article:<p><pre><code> create table transaction (user_id integer, amount integer); insert into transaction values (1, -100); select sum(amount) as balance from transaction;</code></pre>
评论 #13229040 未加载
评论 #13227940 未加载
评论 #13228643 未加载
评论 #13236402 未加载
评论 #13228666 未加载
scandoxover 8 years ago
I got caught by this a couple of years ago, but only because I was using a JSON field and as far as I knew at the time, to modify a JSON value I had to take it out, modify it and write it back. The mistake was ever choosing to use a JSON field for data that was changing rapidly, and being updated from multiple sources. When I detected the issue, I added a FOR UPDATE to my SELECT.<p>It made me realize though the incredible safety I&#x27;d come to take for granted with a more traditional relational approach. Prior to that I would have had a separate table for the data in that JSON field, with each object within it, represented by its own row. Given my scenario that would have been perfectly safe, because the latest update to a specific object was always the right one.<p>The original design choice was perceived as &quot;easier&quot;.
评论 #13230111 未加载
dapover 8 years ago
How are &quot;serializable&quot; transactions in PostgreSQL different from optimistic concurrency control? The docs say:<p>&gt; In fact, this isolation level works exactly the same as Repeatable Read except that it monitors for conditions which could make execution of a concurrent set of serializable transactions behave in a manner inconsistent with all possible serial (one at a time) executions of those transactions. This monitoring does not introduce any blocking beyond that present in repeatable read, but there is some overhead to the monitoring, and detection of the conditions which could cause a serialization anomaly will trigger a serialization failure.<p>As far as I can tell, this doesn&#x27;t make transactions any more serializable; it just fails them if they wouldn&#x27;t have been serializable anyway. And then clients typically retry. That sounds just like OCC. Like OCC, I&#x27;d expect that under any kind of contention, this could lead to very large numbers of failures and retries. It&#x27;s not quite livelock, since at least one client will always make forward progress, but close to it.
评论 #13230900 未加载
评论 #13230109 未加载
评论 #13230078 未加载
quizoticover 8 years ago
Nitpick: while the gist is correct, the 2nd diagram illustrating how transactions don&#x27;t help is subtly misleading. The diagram implies that time flows down in the diagram. If so, then the update on the right won&#x27;t occur until after the commit on the left. The update on the left really does acquire &quot;write&quot; lock on the balance, so the 2nd update on the right cannot occur until after the lock on the left is released when the left commits.<p>That said, the effect is exactly as the author claims. The transaction on the right will ignore the change made by the one on the left.
评论 #13232271 未加载
评论 #13228220 未加载
isoosover 8 years ago
I&#x27;m glad to see optimistic concurrency control mentioned. In my experience even seasoned developers are unaware of this pattern, which should be really the default in many database-handling code.<p>I&#x27;m not aware of ORMs handling it either (except for my in-house code generator). Is there anything out there that handles it well?
评论 #13228564 未加载
评论 #13230799 未加载
评论 #13228406 未加载
评论 #13228328 未加载
评论 #13229629 未加载
评论 #13230358 未加载
评论 #13231276 未加载
评论 #13231623 未加载
buro9over 8 years ago
Hmm.<p>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).<p>This way it all occurs within a single transaction, even though it is several logical steps, and is simple to reason about.
评论 #13227784 未加载
评论 #13230066 未加载
评论 #13229174 未加载
Perceptesover 8 years ago
Great article. This is something I&#x27;ve been thinking about for a while working on Ruma, my Matrix homeserver implementation. I think this is a type of bug that a lot of application developers miss, but the consequences can be quite catastrophic depending on the nature of the data.<p>As a small aside, if anyone is interested in Matrix, Rust, Diesel (the Rust ORM), or the intersection of any of these things, you might be interested in discussing this further on this Ruma issue: <a href="https:&#x2F;&#x2F;github.com&#x2F;ruma&#x2F;ruma&#x2F;issues&#x2F;132" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;ruma&#x2F;ruma&#x2F;issues&#x2F;132</a>
_Codemonkeyismover 8 years ago
I&#x27;m guilty here too.<p>But one side of me wonders why SQL databases do not better adapt to those &#x27;anti-patterns&#x27; in software development, when developers for a variety of reasons are more confident in having logic in their app code than their DB code.
评论 #13231351 未加载
polsoulover 8 years ago
A really good resource is the following book <a href="http:&#x2F;&#x2F;www.apress.com&#x2F;us&#x2F;book&#x2F;9781484207611" rel="nofollow">http:&#x2F;&#x2F;www.apress.com&#x2F;us&#x2F;book&#x2F;9781484207611</a><p>Oracle Database Transactions and Locking Revealed Authors: Kyte, Thomas, Kuhn, Darl<p>It&#x27;s Oracle-specific though, because of one of the authors(Tom Kyte , the Tom behind asktom.oracle.com not so long ago ) I highly recommend it.
indexerrorover 8 years ago
In addition to this, postgres also has Advisory Locks, if you want to handle the locking mechanism client side and don&#x27;t want to fail update by a client that still wants to do the update anyway for some reason.
hmottestadover 8 years ago
Essentially, how to make a bank account in SQL. The author then explains how transactions won&#x27;t help solve the problem, followed by an example with transactions that actually does solve the case.<p>At university we learn that transactions should be serializable and that they are meant for these exact cases.<p>Transactions aren&#x27;t actually true transactions unless they are serializable.<p>Most databases don&#x27;t actually default to serializable transactions, but instead try to get close by implementing snapshot isolation. These aren&#x27;t true transactions, since snapshot isolation doesn&#x27;t truly isolate transactions.<p>The article had a bunch of nice ways to get better isolation than snapshot for a bunch of special cases. These are all very nice, since they can be useful for mainting performance together with integrity.<p>My professors at university still laugh at commercial databases and calls them toys for still not having implemented more efficient serializable transactions.
评论 #13228254 未加载
评论 #13227957 未加载
评论 #13227956 未加载
评论 #13228696 未加载
评论 #13230650 未加载
gloglaover 8 years ago
Please add [2014].<p>I should note that this is not Postres specific - any MVCC ACID database will behave this way. Some use locks instead of MVCC and behave differently. But it definitely belongs into &quot;What every programmer should know about transactions, ollected works&quot;.
评论 #13227780 未加载
评论 #13228003 未加载