HiveBrain v1.2.0
Get Started
← Back to all entries
patternMinor

Read-only transaction anomaly

Submitted by: @import:stackexchange-dba··
0
Viewed 0 times
anomalyonlytransactionread

Problem

I've learned about this anomaly from these papers: https://www.cs.umb.edu/~poneil/ROAnom.pdf (original) https://johann.schleier-smith.com/blog/2016/01/06/analyzing-a-read-only-transaction-anomaly-under-snapshot-isolation.html (short and easy explanation)

Can somebody please explain why is this considered an anomaly? AFAIK, a read-only transaction should see committed changes at the time of its execution, so the result is correct.

Solution

Why is it considered an anomaly? The answer is quoted in your links (emphasis added):

Starting with [BBGMOO95], it was assumed that read-only transactions always execute serializably, without ever needing to wait or abort because of concurrent update transactions. This seemed self-evident because all reads take place at an instant of time, when all committed transactions have completed their writes and no writes of non-committed transactions are visible.

Aside from that surprise, the behaviour is as expected for snapshot isolation, as you say.

But it isn't really a surprise: Snapshot isolation is not serializable isolation (links to my articles, with a SQL Server focus).

Postgres blurred the boundaries with their implementation, Serializable Snapshot Isolation. They claim serializability, and that seems reasonable to me from the brief research I did on it. The second link in your question claims to have found a low error rate, but that likely arises from retrying failed transactions.

That snapshot is not serializable with writes is well-known, for example:

create table a ( x int );
create table b ( x int );
 
-- Session 1 (snapshot)
insert into a select count(*) from b
 
-- Session 2 (snapshot, concurrently)
insert into b select count(*) from a


Snapshot isolation allows both queries to return zero — a result that is clearly not possible in any serial schedule.

Code Snippets

create table a ( x int );
create table b ( x int );
 
-- Session 1 (snapshot)
insert into a select count(*) from b
 
-- Session 2 (snapshot, concurrently)
insert into b select count(*) from a

Context

StackExchange Database Administrators Q#297756, answer score: 3

Revisions (0)

No revisions yet.