Skip to content

gburd/ecto_isolation

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

EctoIsolation

This is a test framework to show how to set the transaction level in ecto using the postgres adapter. I'm using postgres as an example here but this should be directly comparable to other databases.

Scenario

The test problem that we're trying to solve is a "Lost Update" as described by Martin Kleppmann. The specific interleaving of operations would look like this:

begin; set transaction isolation level read committed; -- T1
begin; set transaction isolation level read committed; -- T2
select * from test where id = 1; -- T1
select * from test where id = 1; -- T2
update test set value = 11 where id = 1; -- T1
update test set value = 11 where id = 1; -- T2, BLOCKS
commit; -- T1. This unblocks T2, so T1's update is overwritten
commit; -- T2

The solution to this problem is to use "repeatable read" isolation instead of "read committed".

Running Tests

A single coordinator process spawns two children, both of which start a transaction. The interleavings are controled by the central coordinator in order to cause consistent failures.

In order to run the tests first you need to setup the database:

$ mix ecto.create
$ mix ecto.migrate
$ echo "insert into coupons (code) values ('foo');" | psql -U postgres -d ecto_isolation

Running the tests is done like so:

# This transaction will not fail and you'll lose updates
iex> EctoIsolation.Coordinator.race(EctoIsolation.UnsafeTransaction)

# This transaction uses the correct isolation level and you'll see failures
iex> EctoIsolation.Coordinator.race(EctoIsolation.SafeTransaction)

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Elixir 100.0%