Skip to content

Instantly share code, notes, and snippets.

@haf
Last active September 14, 2015 18:15
Show Gist options
  • Save haf/91cec7cc700ad12f9400 to your computer and use it in GitHub Desktop.
Save haf/91cec7cc700ad12f9400 to your computer and use it in GitHub Desktop.
Txs
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