Fork me on GitHub
#datomic
<
2020-05-22
>
amarjeet07:05:59

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`.

favila12:05:57

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.

favila12:05:02

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

amarjeet12:05:12

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)?

favila12:05:51

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

favila12:05:24

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

favila12:05:03

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

favila12:05:18

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

favila12:05:31

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.

favila12:05:45

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)

amarjeet13:05:36

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