Fork me on GitHub

Hi, I am wondering if Datomic addresses read-conflict or write-skew scenarios at the commit time? I discovered that Clojure has ensure that can be used along with ref to achieve similar results. To elaborate the above point with an example: Lets say that `process A` reads `a` from DB and writes to `b` in the DB. While `process A`  was in progress, `process B` mutated (and committed) `a`  with a different value. So, when `process A` tries to commit `b`, it should be retried in order to address conflicts in the read-value of `a`.


There are three mechanisms: transaction functions, schema invariants, and attribute predicates/ensure. Transaction functions cannot skew because they effectively have a global lock on the database while they run; and they can abort based on the before-transaction db value by throwing. However multiple txfns cannot see the assertions/retractions of other datoms and txfns in the same tx, nor can they see the after-transaction value. (:db/cas is a transaction function.) schema invariants (cardinality, uniqueness, and identity) detect datom conflicts in the after-transaction value and abort, or upsert to an entity possibly created in another transaction. attribute predicates and ensure are a more powerful generalization of this--they can abort on any condition visible in the after-transaction value.


Note all these mechanisms merely provide different ways to read or abort. Retries are up to you


So, it means that the situation i described above (read-conflict for ‘a’) will never arise because transactions are being literally serialized (global db lock)?


it can happen, but not in the traditional way they would happen in SQL


datomic transactions are sets of atomic assertions and retractions, applied serially by a single writer (the transactor)


how those sets are made, and whether those sets can be applied in any order, is still a concern


transactions from a given peer will be applied in the same order as submitted relative to one another, but may be interleaved with transactions from other peers


but each of those transaction sets were built (presumably) by reading a database value and conditionally producing a new one. so that’s read schew-ish.


You can avoid the possibly stale read by preparing the set in a transaction function (i.e. with a read lock), but it’s still just producing a set of assertions and retractions, not actually immediately writing (meaning: other transaction functions in the same db won’t see “writes” by other assertions/retractions in the same tx)


Hmm, okay, i ll read further in the docs, thanks :)