Transactions
Sami Rollins
Overview
Example
ACID
ACID – Bank account example
Ensuring isolation
Ensuring isolation
T1: T2:
a.withdraw(100) c.withdraw(100)
b.deposit(100) d.deposit(100)
Serial equivalence
T: U:
bal = b.getBalance() bal = b.getBalance()
b.setBalance(bal*1.1) b.setBalance(bal*1.1)
a.withdraw(bal/10) c.withdraw(bal/10)
Lost updates
T:
bal = b.getBalance()
b.setBalance(bal*1.1)
a.withdraw(bal/10)
U:
bal = b.getBalance()
b.setBalance(bal*1.1)
c.withdraw(bal/10)
Inconsistent retrievals
T:
a.withdraw(100)
b.deposit(100)
U:
aBranch.branchTotal()
Read skew
T:
a.withdraw(100)
b.deposit(100)
U:
balance = a.getBalance()
balance = b.getBalance()
Dirty reads
T: U:
bal1 = a.getBalance()
a.setBalance(bal1+10)
bal2 = a.getBalance()
a.setBalance(bal2+20)
commit
abort
Premature writes (Dirty writes)
T: a.setBalance($105) - (before image: 100)
U: a.setBalance($110) - (before image: 105)
Write skew
T:
bal = b.getBalance()
if a.balance >= bal/10
b.setBalance(bal*1.1)
a.withdraw(bal/10)
U:
bal = b.getBalance()
if c.balance >= bal/10
b.setBalance(bal*1.1)
c.withdraw(bal/10)
Serial equivalence
T:
bal = b.getBalance()
b.setBalance(bal*1.1)
a.withdraw(bal/10)
U:
bal = b.getBalance()
b.setBalance(bal*1.1)
c.withdraw(bal/10)
Serial equivalence
T: U:
x=read(i); read(j);
write(i, 10); write(j, 30);
write(j, 20) z=read(i)
Example
T: x=read(j); y=read(i); write(j, 44); write(i, 33)
U: x=read(k); write(i, 55); y=read(j); write(k, 66)
Achieving serial equivalence
Two-phase locking
Strict two-phase locking
Recap
T: U:
read(a) read(d)
write(b, 10) write(d, 30)
write(c, 20) z=read(f)
Recap - Option 1: Global Lock
lock.acquire()
t1: read(a)
t2: write(b, 10)
t3: write(c, 20)
lock.release()
lock.acquire()
u1: read(d)
u2: write(d, 30)
u3: z=read(f)
lock.release()
Recap - Option 1: Global Lock
lock.acquire()
t1: read(a)
t2: write(b, 10)
t3: write(c, 20)
lock.release()
lock.acquire()
u1: read(d)
u2: write(d, 30)
u3: z=read(f)
lock.release()
No concurrency allowed!
Recap - Option 2: Lock per object
T locks a
t1: read(a)
T unlocks a
U locks d
u1: read(d)
u2: write(d, 30)
U unlocks d
T locks b
t2: write(b, 10)
U locks f
u3: z=read(f)
U unlocks f
T locks c
t3: write(c, 20)
T unlocks b; T unlocks c
Recap - Option 2: Lock per object
T locks a
t1: read(a)
T unlocks a
U locks a; U locks d
u1: read(d)
u2: write(a, 30)
U unlocks a; U unlocks d
T locks b
t2: write(b, 10)
U locks f
u3: z=read(f)
U unlocks f
T locks f
t3: write(f, 20)
T unlocks b; T unlocks f
Recap - Option 2: Lock per object
T locks a
t1: read(a)
T unlocks a
U locks a; U locks d
u1: read(d)
u2: write(a, 30)
U unlocks a; U unlocks d
T locks b
t2: write(b, 10)
U locks f
u3: z=read(f)
U unlocks f
T locks f
t3: write(f, 20)
T unlocks b; T unlocks f
Interleaving is not serially equivalent!
Recap - Option 2: Lock per object
T locks a
t1: read(a) (a -> 100)
T unlocks a
U locks a; U locks d
u1: read(d) (d -> 200)
u2: write(a, 30) (a = 30)
U unlocks a; U unlocks d
T locks b
t2: write(b, 10) (b = 10)
U locks f
u3: z=read(f) (f -> 300)
U unlocks f
T locks f
t3: write(f, 20) (f = 20)
T unlocks b; T unlocks f
a=100; d=200; f=300
T sees a as 100; U sees f as 300
T then U - T sees a as 100 U sees f as 20
U then T - U sees f as 300 T sees a as 30
Recap - Option 3: Two-Phase Locking
T locks a
t1: read(a)
T unlocks a
U locks a; U locks d
u1: read(d)
u2: write(a, 30)
U unlocks a; U unlocks d
T locks b
t2: write(b, 10)
U locks f
u3: z=read(f)
U unlocks f
T locks f
t3: write(f, 20)
T unlocks b; T unlocks f
Cannot release a lock and then acquire a new lock.
Recap - Option 3: Two-Phase Locking
T locks a
t1: read(a)
U locks d
u1: read(d)
T locks b
t2: write(b, 10)
T locks f
t3: write(f, 20)
T unlocks a; T unlocks b
T unlocks f
U locks a; U locks f
u2: write(a, 30)
u3: z=read(f)
U unlocks a; U unlocks d; U ulocks f
Recap - Option 3: Two-Phase Locking
T locks a
t1: read(a)
U locks d
u1: read(d)
T locks b
t2: write(b, 10)
T locks f
t3: write(f, 20)
T unlocks a; T unlocks b
T unlocks f
U locks a; U locks f
u2: write(a, 30)
u3: z=read(f)
U unlocks a; U unlocks d; U ulocks f
T aborts
T may decide to abort!
Recap - Option 4: Strict Two-Phase Locking
T locks a
t1: read(a)
U locks d
u1: read(d)
T locks b
t2: write(b, 10)
T locks f
t3: write(f, 20)
T aborts (unlock all)
U locks a; U locks f
u2: write(a, 30)
u3: z=read(f)
U commits (unlock all)
Example
T: x=read(j); y=read(i); write(j, 44); write(i, 33)
U: x=read(k); write(i, 55); y=read(j); write(k, 66)
Deadlock
T: a.deposit(100); b.withdraw(100)
U: b.deposit(50); a.withdraw(50)
Preventing deadlock
Wait-for graph
T
U
Detecting deadlock
Distributed transactions
Distributed transactions
Two-phase commit
Handling failure