Covers 3 new anomalies proposed by A Critique of ANSI SQL Isolation Levels - Microsoft.
P4 (Lost Update)
*R1[x]...W2[x]...W1[x]...C1*
This happens when a transaction T1 reads a row ‘x’ and then T2 updates the row ‘x’ (possibly based on a previous read), then T1 (based on its earlier read value) updates the row and commits.
T1 | T2 |
---|---|
BEGIN | |
R(x) | |
BEGIN | |
W(x) | |
W(x) | |
COMMIT | |
COMMIT |
Here, the data written by T2 will be ‘lost’.
It might seem similar to P0 (dirty write), but it’s not. The difference is that T1 has to read the value first & commit this time (the order relative to commit of T2 doesn’t matter).
Example: r1[x=100] r2[x=100] w2[x=120] c2 w1[x=130] c1
T1 and T2 both read x as 100. T2 updates x to 130 & commits, T1 then updates x to 130 & commits. Value written by T2 is essentially ‘lost’.
It’s easy to confuse this with TOCTTOU, which is a similar but broader concept I’d rather call a race condition than just a database isolation problem. It may happen even with a serializable database if you don’t pay attention to properly using database transactions.
Now let’s talk about two anomalies arising from a database constraint between two rows x and y.
A5A Read Skew
r1[x]...w2[x]...w2[y]...c2...r1[y]...(c1 or a1)
Suppose transaction T1 reads x, and then a second transaction T2 updates x and y to new values and commits. If now T1 reads y, it may see an inconsistent state, and therefore produce an inconsistent state as output.
Example: (x+y=100) r1[x=50] w2[x=10] w2[y=90] c2 r1[y=90] c1
Let’s suppose we are dealing with a table for joint bank accounts where each row is the individual account for the joint account holder. The database constraint is that at all times, the sum of x+y must be equal to 100.
The values of x & y before start of any transaction is 50 each, so the sum is 100. Now T1 reads value of x as 50, then T2 transfers 40 from x to y and commits. Now T1 reads the value of y, which comes as 90, thus appearing to T1 that the db constraint is violated as 50 + 90 = 140.
A5B Write Skew
r1[x]...r2[y]...w1[y]...w2[x]...(c1 and c2)
Suppose T1 reads x and y, which are consistent with some database constraint, and then a T2 reads x and y, writes x, and commits. Then T1 writes y. If there were a constraint between x and y, it might be violated.
Example: (x+y>=0) r1[x=50] r1[y=50] r2[x=50] r2[y=50] w1[y=-40] w2[x=-40] c1 c2
Same table as in the example for A5A, the database constraint this time is that at all times, x+y must be non-negative, even if any of the individual accounts are negative.
Now T1 reads value of x as 50, then T2 reads the value of y as 50. Now both deduct 90 from y & x respectively, thinking they are safely adhering to the database constraints. Once both T1 & T2 have committed, the database reads x+y = -80, violating the constraint.