"...able withdraw more money than they had in their account...Most so-called ACID databases — for example Postgres, MySQL, Oracle or MS SQL Server — would not have prevented this race condition in their default configuration." The author didn't really show that this was true. He obviously understands isolation well, so I would tend to believe him, but it would be nice to see an example. In a simple case (not sure tha…
I think this could happen if you do not use 'compare-and-swap' and simply update account set balance=balance-9 twice at the same time when the account balance is 10. The account balance won't go below zero but you ended up withdrawing twice.
Hermitage: Testing the “I” in ACID
21–30 of 34 posts
Re: Hermitage: Testing the “I” in ACID
#22"...able withdraw more money than they had in their account...Most so-called ACID databases — for example Postgres, MySQL, Oracle or MS SQL Server — would not have prevented this race condition in their default configuration." The author didn't really show that this was true. He obviously understands isolation well, so I would tend to believe him, but it would be nice to see an example. In a simple case (not sure tha…
It's typically called Write Skew. Wikipedia discusses it on the snapshot isolation page ( http://en.wikipedia.org/wiki/Snapshot_isolation ). Also, Peter Bailis's blog has info and links to papers if you want more detail ( http://www.bailis.org/blog/when-is-acid-acid-rarely/ )
What I don't know is about the particular problem the exchange encountered, and why postgres's isolation would not have prevented it. Based on the very brief descriptions of the problem that I've seen, it seems like postgres would have prevented it, but I don't have enough information to say for sure.
Re: Hermitage: Testing the “I” in ACID
#23"Internet commenters, in their infinite wisdom, were quick to point out that if you’re dealing with money, you had better use an ACID database. But there was a major flaw in their argument. Most so-called ACID databases — for example Postgres, MySQL, Oracle or MS SQL Server — would not have prevented this race condition in their default configuration."
I hesitate because I don't really understand the details of the situation the exchange faced. But, going by the linked references here:
https://bitcointalk.org/index.php?topic=499580 http://www.reddit.com/r/Bitcoin/comments/1wtbiu/how_i_stole_...
it appears that the pattern in question, if translated very unnaturally to SQL, is something like:
CREATE TABLE account(id int8, balance numeric);
...
BEGIN;
SELECT balance FROM account WHERE id = 123;
-- application sees 100, subtracts 90, sees that
-- it's still positive and does:
UPDATE account SET balance = 10 WHERE id = 123;
COMMIT;
Technically speaking, running that in postgres in the default configuration (read committed) is prone to a race, and you'd need to use repeatable read or serializable mode to protect you.But that's ridiculous. Anyone using SQL would instead do:
CREATE TABLE account(id int8, balance numeric, check(balance >= 0));
...
UPDATE account SET balance = balance - 90 WHERE id = 123;
And that is not prone to a race. Try it in any version of postgres, in any configuration. You can't get double withdrawls (where only one takes effect), and you can't get it to go below zero.So, the author is technically right: (a) if you translate the NoSQL-isms into SQL in an unnatural way; and (b) don't bother to use SERIALIZABLE mode, which costs very little in most situations.
I agree with the author that isolation is tricky, and developers should not be expected to understand the nuances. And I applaud the development of a testing framework to really understand the various kinds of isolation and how they apply to different products. But the example is a bad one, because it actually does work just fine in postgres, and probably many other systems.
Re: Hermitage: Testing the “I” in ACID
#24> The idea of isolation is that we want our database to be able to process several transactions at the same time (otherwise it would be terribly slow)
Not necessarily true. Things like Prevayler and LMAX provide isolation by processing transactions one at a time, and they're very fast. They manage this by keeping everything relevant hot in RAM. LMAX, for example, can do 6 million TPS for a financial trading platform. You can read Martin Fowler writing about LMAX here: http://martinfowler.com/articles/lmax.html
Re: Hermitage: Testing the “I” in ACID
#25I strongly rebut the following claim, which is central to the article: "Internet commenters, in their infinite wisdom, were quick to point out that if you’re dealing with money, you had better use an ACID database. But there was a major flaw in their argument. Most so-called ACID databases — for example Postgres, MySQL, Oracle or MS SQL Server — would not have prevented this race condition in their default configurat…
Although your second example is probably what a human would write, an ORM framework would very likely generate a transaction looking like your first example.
Another example would be inserting a transaction into a table, and summing the transactions in the account in order to calculate the account balance. Making that safe requires preventing phantom reads, which means requiring serializability.
You say serializable costs very little in most situations. I can't claim to know what most situations are like, but all I know is that I've seen many people who have tried serializable and found it too slow for them. User a-priori gives an example elsewhere on this thread: http://www.michaelmelanson.net/2014/03/20/transactions/
My point is that weak isolation is very subtle, easy to get wrong, and you don't know that you got it wrong until it's too late. We need better understanding and better tools so that concurrency is less easy to screw up.
Re: Hermitage: Testing the “I” in ACID
#26Re: Hermitage: Testing the “I” in ACID
#27Re: Hermitage: Testing the “I” in ACID
#28I strongly rebut the following claim, which is central to the article: "Internet commenters, in their infinite wisdom, were quick to point out that if you’re dealing with money, you had better use an ACID database. But there was a major flaw in their argument. Most so-called ACID databases — for example Postgres, MySQL, Oracle or MS SQL Server — would not have prevented this race condition in their default configurat…
Your first ("very unnatural") example is what I had in mind. And since read committed is the default isolation level in most RDBMS, it is prone to the lost update anomaly. (In MySQL, repeatable read is the default, but its implementation of repeatable read doesn't prevent lost updates.) Note I did point out that I'm referring to the default configuration, not the strongest supported isolation level. Although your sec…
And the point about ORMs is valid, but still not enough to back up your unqualified claim that using postgres would not have solve the problem. It might not have, but postgres offers a lot of tools to solve this problem (we didn't even discuss SELECT ... FOR UPDATE), and even inexperienced users are at least more likely to have stumbled into one of those solutions.
I very much agree that isolation issues are subtle traps for many users, even in SQL. I would like to see SERIALIZABLE become more common, and eventually the default, in postgres. I also like the fact that you're writing real tools to check up on these in a formal way.
But please be a little careful when making statements like that, because it can turn people away from the systems most likely to help them.
Re: Hermitage: Testing the “I” in ACID
#29Earlier quoted context omitted.
It's typically called Write Skew. Wikipedia discusses it on the snapshot isolation page ( http://en.wikipedia.org/wiki/Snapshot_isolation ). Also, Peter Bailis's blog has info and links to papers if you want more detail ( http://www.bailis.org/blog/when-is-acid-acid-rarely/ )
I know, in general, about various kinds of serialization anomalies, and I know (in moderate detail) how all of the isolation modes are implemented in postgres. What I don't know is about the particular problem the exchange encountered, and why postgres's isolation would not have prevented it. Based on the very brief descriptions of the problem that I've seen, it seems like postgres would have prevented it, but I don'…
Think of a transaction that inserts a row representing a withdrawal, updates a materialized total balance, and checks that it's positive. Under snapshot isolation, two concurrent instances of this transaction could commit. The materialized balance would reflect only one of the debits however, and would be inconsistent vs queries that recompute the aggregate in full.
Postgres pre version 9.2-ish would allow this situation even in "serializable" mode. Later versions wouldn't.
Re: Hermitage: Testing the “I” in ACID
#30I strongly rebut the following claim, which is central to the article: "Internet commenters, in their infinite wisdom, were quick to point out that if you’re dealing with money, you had better use an ACID database. But there was a major flaw in their argument. Most so-called ACID databases — for example Postgres, MySQL, Oracle or MS SQL Server — would not have prevented this race condition in their default configurat…
I would disagree that offering an alternate solution that avoids the problem is a rebuttal of the fact that there are quirks in isolation level implementations across RDBMSs that can surprise even seasoned developers.