JEPSEN

Read Uncommitted

Read uncommitted is a consistency model which prohibits dirty writes, where two transactions modify the same object concurrently before committing. In the ANSI SQL specification, read uncommitted is presumed to be the default, most permissive consistency model, allowing all behaviors; however, Berenson et al argued that it should, in fact, prohibit dirty writes.

Read uncommitted is a transactional model: operations (usually termed “transactions”) can involve several primitive sub-operations performed in order. It is also a multi-object property: operations can act on multiple objects in the system.

Read uncommitted can be totally available: in the presence of network partitions, every node can make progress. Without sacrificing availability, you can also ensure that transactions do not read uncommitted state by choosing the stronger read committed.

Note that read uncommitted does not impose any real-time constraints. If process A completes write w, then process B begins a read r, r is not necessarily guaranteed to observe w. For a transactional model that provides real-time constraints, consider strict serializability.

Moreover, read uncommitted does not require a per-process order between transactions. A process can observe a write, then fail to observe that same write in a subsequent transaction. In fact, a process can fail to observe its own prior writes, if those writes occurred in different transactions.

Like serializability, read uncommitted allows pathological orderings. For instance, a read uncommmitted database can always return the empty state for any reads, by appearing to execute those reads at time 0. It can also discard write-only transactions by reordering them to execute at the very end of the history, after any reads. Operations like increments can also be discarded, assuming the result of the increment is never observed. Luckily, most implementations don’t seem to take advantage of these optimization opportunities.

Formally

The ANSI SQL 1999 spec places essentially no constraints on the behavior of read uncommitted. Any and all weird behavior is fair game.

However, as Berenson, Bernstein, et al observed, the ANSI specification allows multiple intepretations, and one of those interpretations (the "anomaly interpretation) still admits nonserializable histories for “serializable” systems. Instead, we prefer Adya’s formalization of transactional isolation levels, which provides a concise definition of the preventative interpretation. In this model, read uncommitted prohibits:

  • P0 (Dirty Write): w1(x) … w2(x)

but allows:

  • P1 (Dirty Read): w1(x) … r2(x)
  • P2 (Fuzzy Read): r1(x) … w2(x)
  • P3 (Phantom): r1(P) … w2(y in P)

Here w denotes a write, r denotes a read, and subscripts indicate the transaction which executed that operation. The notation “…” indicates a series of micro-operations except for a commit or abort. P indicates a predicate.

For a state-based formalization, see Crooks, Pu, Alvisi, & Clement: Seeing is Believing: A Client-Centric Specification of Database Isolation.