Last active
September 14, 2015 18:15
-
-
Save haf/91cec7cc700ad12f9400 to your computer and use it in GitHub Desktop.
Txs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Trouble with Transactions | |
This is a piece on why you should use transactions. | |
The trouble with transactions in contemporary programming is that the APIs for | |
transactions don't fit how applications are written. Say you want to support | |
transactions in your app, how would you go about? | |
First of all, you're already doing implicit transactions around each SQL | |
statements. So you are moving away from this model if you're changing how you | |
deal with transactions. | |
Second, you probably want to use Serializable Snapshot Isolation (MVCC without | |
Write Skew), so you start by bumping the isolation level of your PostgreSQL | |
database. Let's assume [it works without | |
bugs](http://www.bailis.org/papers/feral-sigmod2015.pdf) | |
Third, you now want to start adapting your data access patterns, to make sure | |
that you read every datum that you use for logic and as the base of your change | |
to your domain model. This means that transactions may fail to commit because | |
another transaction updated what you read; and this is fine. | |
Fourth, you need to make sure that your data changes don't call APIs that start, | |
abort or rollback transactions implicitly; e.g. by providing a transaction monad | |
that only continues to call your bound functions if it's still ongoing. | |
Fifth, you need to make your end-use-case operations very explicit; perhaps by | |
encapsulating them in the Command pattern. You also need to make sure that you | |
don't call functions that deal with transactions themselves. | |
Sixth, create separate policies for read-only and write operations. | |
Read-operations should automatically re-run if they are rolled back. Write | |
operations should not; they need to re-execute the logic starting from deciding | |
whether they are needed or even possible anymore – something a previous read | |
operation decided. If the write-op is still a GO, then re-execute the piece of | |
code that reads what is to be decided with and then start the write operation. | |
Seven, log hotspots that roll back often and see if you can't make their | |
read-set smaller to avoid starvation. | |
Eight, try to perform all the reading before the writes so that you grow your | |
read-set before you start to write. | |
So the trouble with transactions is that you have to have the mental model of | |
something that's hidden behind your application. Like described above, you will | |
have to think of the database's execution model. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment