Concurrency Control Techniques Prepared by: Remedios de Dios Bulos Outline • Lock-Based Protocols – – – – What is locking? What are locks? Binary locks Shared/ Exclusive locks (Read/Write Locks) • Timestamp-Based.
Download ReportTranscript Concurrency Control Techniques Prepared by: Remedios de Dios Bulos Outline • Lock-Based Protocols – – – – What is locking? What are locks? Binary locks Shared/ Exclusive locks (Read/Write Locks) • Timestamp-Based.
Concurrency Control Techniques Prepared by: Remedios de Dios Bulos Outline • Lock-Based Protocols – – – – What is locking? What are locks? Binary locks Shared/ Exclusive locks (Read/Write Locks) • Timestamp-Based Protocols • Validation-Based Protocols What is locking? • It is a procedure used to control concurrent access to data; • When one data is accessing the database, a lock may deny access to other transactions to prevent incorrect results; • Ensures serializability of concurrent transactions; Concurrency Problems Lost update problem Time T1 T2 balx t1 begin _transaction 100 t2 begin _transaction read(balx) 100 t3 read(balx) balx=balx + 100 100 t4 balx=balx - 10 write(balx) 200 t5 write(balx) t6 commit commit 90 90 Solution: Prevent T1 from reading the value of balx until after T2‘s update has been completed. balx should be 190. Concurrency Problems Lost update problem Time t1 T1 t2 begin _transaction read(balx) t3 T2 balx begin _transaction LOCK 100 read(balx) 100 balx=balx + 100 100 balx=balx - 10 t4 t5 write(balx) write(balx) 200 UNLOCK90 commit t6 commit 90 Solution: Prevent T1 from reading the value of balx until after T2‘s update has been completed. balx should be 190. What is a lock? • A variable associated with a data item that describes the status of the item with respect to possible operations that can be applied to it. • Generally, there is one lock for each data item in the database. X lock-X Y lock-Y Z lock-Z Types of Locks • Binary locks: • only two states of a lock; • too simple and too restrictive; • not used in practice. • Shared/exclusive locks: which provide more general locking capabilities and are used in practical database locking schemes. • Read Lock as a shared lock, • Write Lock as an exclusive lock. Binary Locks • A binary lock can have two states or values: locked and unlocked (or 1 and 0) locked or 1 X lock-X unlocked or 0 Binary Locks • A binary lock enforces mutual exclusion on the data item; i.e., at a time, only one transaction can hold a lock. HOLDS lock on X Can’t HOLD a lock on X T1 T2 Binary Locks • A distinct lock is associated with each database item. • If the value of the lock on X is 1 (locked), item X cannot be accessed by a database operation that requests the item. lock-X X Can’t read Can’t Write 1 T1 • If the value of the lock on X is 0 (unlocked), the item can be accessed when requested. Can read Can write 0 T1 Operations on Binary Locks • lock(X) • unlock(X) Operations on Binary Locks lock(X): • A transaction requests access to an item X by first issuing a lock(X) operation. • If LOCK-X =1, the transaction is forced to wait. • If LOCK-X = 0, it is set to 1 (the transaction locks the item) and the transaction is allowed to access item X. lock(X) lock-X T1 Waiting … 1 T1 HOLDS lock on X T1 Can access X 0 1 Algorithm: lock(X) B: if LOCK-X =0 (*item is unlocked) then LOCK-X 1 (*lock the item) else begin wait (until lock-X =0 and the lock manager wakes up the transaction) go to B end; Operations on Binary Locks • unlock(X): sets LOCK-X to 0 (unlocks the items) so that X may be accessed by other transactions; lock-X 0 1 unlock(X) T1 Algorithm: unlock(X) LOCK-X 0 (*unlock the item) if any transactions are waiting then wakeup one of the waiting transactions Operations on Binary Locks • lock(X) and unlock(X) operations must be implemented as indivisible units; that is, no interleaving should be allowed once a lock or unlock operation is started until the operation terminates or the transaction must wait until the lock_item goes through. Operations on Binary Locks • wait command within the lock(X) operation is usually implemented by putting the transaction on a waiting queue for item X until X is unlocked and the transaction can be granted access to it. Other transactions that also want to access X are placed on the same queue. Hence, the wait is considered to be outside the lock(X) operation. Implementation of Lock_Item • Lock manager: a subsystem that keeps track of and controls access to locks. • A binary-valued variable, LOCK is associated with each data item X in the database • LOCK TABLE • A table of rows and three fields: <data item name, LOCK, locking transaction> • Plus queue for transactions that are waiting to access the item Lock Manager D Item Lock X 0 or 1 T2 T3 Trans T1 t4 Binary Locking Scheme Every transaction must obey the following rules, which are enforced by the LOCK MANAGER 1. A transaction T must issue the operation lock(X) before any read(X) or write(X) operations are performed in T. 2. A transaction T must issue the operation unlock(X) after all read(X) and write(X) operations are completed in T. T1 begin lock(X) read(X) write(X) unlock(X) commit Binary Locking Scheme 3. A transaction T will not issue a lock(X) operation if it already holds the lock on item X. 4. A transaction T will not issue an unlock(X) operation on X unless it already holds the lock on item X. T1 begin lock(X) read(X) lock(X) write(X) unlock(X) unlock(Y) commit T1 begin lock(X) read(X) write(X) unlock(X) commit T2 T3 begin lock(X) read(X) write(X) begin lock(X) read(X) unlock(X) commit write(X) unlock(X) commit D Item Lock Trans 0 101100 T1 T2 T3 X T2 T3 T3 Problem: Given two schedules T1 and T2. T1 transfers an amount (500) from account X to account Y. T2 deposits an amount (1000) to account X. Initial values of X = 8,500; Y = 3,500. Solution: After the successful execution of both transactions, the final values should be: Schedule T1, T2: X = 9000; Y = 4000 Schedule T2, T1: X = 9000; Y = 4000 T1 and T2 are interleaved: T1 T2 DB X = 8,500; Y=3,500 read(X); X:=X-500; read(X); X:=X+1000; write(X); read(Y); X=8000 write(X); Y:=Y+500; write(Y); X=9500 Y=4000 T1 and T2 are interleaved: T1 T2 DB X = 8,500; Y=3,500 read(X); X:=X-500; read(X); X:=X+1000; write(X); read(Y); X=8000 write(X); Y:=Y+500; write(Y); X=9500 Y=4000 INCONSISTENT: X should be 9000 What went wrong? T2 reads the value of X (old) before T1‘s update of X has been completed. T1 T2 DB X = 8,500; Y=3,500 read(X); X:=X-500; read(X); X:=X+1000; write(X); read(Y); X=8000 write(X); Y:=Y+500; write(Y); X=9500 Y=4000 Solution: Prevent T2 from reading the value of X until after T1‘s update of X has been completed. T1 T2 DB X = 8,500; Y=3,500 read(X); X:=X-500; read(X); X:=X+1000; write(X); read_item(Y); X=8000 write(X); Y:=Y+500; write(Y); X=9500 Y=4000 Using Binary Locks T1 T2 DB X = 8,500; Y=3,500 lock(X) read_item(X); X:=X-500; lock(X) write(X); The request of T2 is not granted since X is locked to T1 X= 8000 lock(Y) read(Y); Y:=Y+500; Waiting write(Y); Y = 4000 unlock(X) unlock(Y) CONSISTENT read(X); X:=X+1000; write(X); unlockX) X= 9000 Binary Locking Problems • Problem: – T1: adds the value of item A to items B to Z; – T2: queries the value of item A T1 T2 DB lock(A) The request of T2 is not granted since A is locked to T1 lock(A) read(A); lock(B) Problem: Too restrictive, that is, at most only one transaction can hold a lock on a given item read(B); B:=B+A; … lock(Z) Waiting read(B); Z:=Z+A; unlock(A) read(A); print(A); unlock(A) unlock(B) … Solution: Allow several transactions to access the same item, if the access is for reading purposes only T2 is finally allowed to access item A. Shared/Exclusive (or Read/Write) locks • A lock associated with an item X, LOCK(X), now has three possible states: – “read_locked”, – “write_locked”, or – “unlocked”. X lock-X read-locked / rl unlocked / ul write-locked / wl Shared/Exclusive (or Read/Write) locks A read_locked item is also called shared-locked, because other transactions are allowed to read the item. A write_locked item is called exclusive-locked, because a single transaction exclusively holds the lock on the item Shared/Exclusive (or Read/Write) locks • LOCK TABLE: Lock table will have four fields: <data item name, LOCK, no_of_reads, locking_transaction(s) > • Value of LOCK: Some encoded value for read/encoded value for write. • write-locked, the value of locking_transaction is a single transaction that holds the exclusive (write) lock on X. • read-locked, the value of locking transaction(s) is a list of one or more transactions that hold the shared (read) lock on X. Data item Lock No of Reads x RL 2 y WL 0 z UL 0 Locking Trans T1 T2 T1 Queue of waiting transactions Shared/Exclusive (or Read/Write) locks Rules for Read/Write Locks 1. A transaction T must issue the operation read_lock(X) or write_lock(X) before any read(X) operation is performed in T. 2. A transaction T must issue the operation write_lock(X) before any write(X) operation is performed in T. T1 T2 begin begin read-lock(X) write-lock(X) read(X) read(X) write-lock(X) write(X) write(X) unlock(X) unlock(X) commit commit Shared/Exclusive (or Read/Write) locks Rules for Read/Write Locks 3. A transaction T must issue the operation unlock(X) after all read(X) and write(X) operations are completed in T. 4. A transaction T will not issue a read_lock(X) operation if it already holds a read (shared) lock or a write (exclusive) lock on item X. EXCEPTIONS: downgrading of lock from write to read) T1 T2 begin begin read-lock(X) write-lock(X) read(X) read-lock(X) write-lock(X) read(X) write(X) write(X) unlock(X) unlock(X) commit commit Shared/Exclusive (or Read/Write) locks Rules for Read/Write Locks 5. A transaction T will not issue T1 T2 begin begin write-lock(X) write-lock(X) read(X) read(X) Exceptions: Upgrading of lock from read to write) write-lock(X) write-lock(X) write(X) write(X) 6. A transaction T will not issue an unlock(X) operation unless it already holds a read (shared) lock or a write (exclusive) lock on item X. unlock(X) unlock(X) commit unlock(Y) a write_lock(X) operation if it already holds a read(shared) lock or write (exclusive) lock on item X. commit Algorithm: read_lock(X) B: if LOCK(X) = “unlocked” then begin LOCK(X) “read-locked”; no_of_reads(X) 1 end elseif LOCK(X) = “read-locked” then no_of_read(X) no_of_reads(X) + 1 else begin wait (until LOCK(X) = “unlocked” and the lock manager wakes up the transaction); go to B end Algorithm: write_lock(X) B: if LOCK(X) = “unlocked” then begin LOCK(X) “write-locked”; else wait (until LOCK(X) = “unlocked” and the lock manager wakes up the transaction); go to B end; Algorithm: unlock(X) B: if LOCK(X) = “write-locked” then begin LOCK(X) “unlocked”; wakeup one of the waiting transactions, if any end else if LOCK(X) = “read-locked” then begin no_of_read(X) no_of_reads(X) - 1 if no_of_reads(X)=0 then begin LOCK(X) =“unlocked” wakeup one of the waiting transactions, if any end end; T1 T2 T3 begin write-lock(X) begin read(X) read-lock(X) begin write(X) read(X) read-lock(X) unlock(X) read(X) commit unlock(X) unlock(X) commit commit Data item X Lock No of Reads Locking Trans UL WL UL RL UL Waiting queue 01210 T2 T3 T3 T1 T2 T3 T3 Shared/Exclusive (or Read/Write) locks Conversion of Locks UPGRADING: If T is the only transaction holding a read lock on X at the time it issues the write_lock(X) operation, the lock can be upgraded, otherwise, the transaction must wait. DOWNGRADING: It is also possible for a transaction T to issue a write_lock(X) and then later on to downgrade the lock by issuing a read_lock(X) operation. T1 T2 begin begin read-lock(X) write-lock(X) read(X) read(X) write-lock write(X) write(X) read-lock(X) unlock(X) read(X) commit unlock(X) commit Lock-compatibility matrix S X s true false x false false Example • Problem: – T1: adds the value of item A to items B to Z; – T2: queries the value of item A T1 T2 DB read-lock(A) The request of T2 is granted since A is shared locked to T1 read(A); T2 is finally allowed to access item A. read-lock(A) read(A); print(A); unlock(A) write-lock(B) read(B); B:=B+A; … write-lock(Z) read(Z); Z:=Z+A; unlock(A) unlock(B) … T2 is soon done B must be exclusive-locked since it is to be written to. However, locking can violate serializability Locking: Violation of Serializability Problem: Given two transaction T1 and T2 T1 adds the content of Y to X; ( X = X+Y) T2 adds the content of X to Y; (Y = Y + X) Initial values : X= 20, Y=30 Solution 1: T1,T2 T1: X = X + Y; 20+30; X= 50 ; Y=30 T2: Y = Y + X; 30+50; X=50; Y=80 Solution 2: T2,T1 T2: Y = Y + X; 30+20; X=20; Y=50 T1: X = X + Y; 20+50; X= 70 ; Y=50 Serial Schedule: T1,T2 T1 T2 DB X=20; Y=30 read(Y); read(X); X:=X+Y; write(X) X = 50 read(X); New value of X is read, which is 50 read(Y) Y=Y+X write(Y) Y = 80 Old value of Y is read, which is 30 Serial Schedule: T2,T1 T2 T1 DB X=20; Y=30 read(X); read(Y) Y=Y+X write(Y) Y= 50 read(Y); New value of Y is read, which is 50 read(X); X:=X+Y; write(X) X=70 Old value of X is read, which is 20 T1 T2 DB X=20; Y=30 read-lock(Y) Final Values: read(Y); X= 50 unlock(Y) Y=50 read-lock(X) Database is inconsistent read(X); unlock(X) write-lock(Y) Old value of Y is read, which is 30 read(Y) Y=Y+X write(Y) Y = 50 unlock(Y) write-lock(X) read(X); Old value of X is read, which is 20 X:=X+Y; write(X) unlock(X) X = 50 Locking Can Violate Serializability Findings: • T1, T2: X=50; Y=80 • T2, T1: X=70, Y=50 • Interleaved schedule using R/W locking: X=50; Y=50 • Therefore, interleaved schedule is not serializable What is wrong with the example? T1 T2 DB X=20; Y=30 T1 T2 read-lock(Y) DB X=20; Y=30 read(Y); read(Y); unlock(Y) read(X); read-lock(X) X:=X+Y; read(X); write(X) unlock(X) read(X); write-lock(Y) read(Y) read(Y) Y=Y+X Y=Y+X write(Y) X = 50 Y = 50 write(Y) Y = 80 unlock(Y) write-lock(X) read(X); X:=X+Y; write(X) unlock(X) X = 50 Y in T1 and X in T2 were unlocked too early … both old values were read Locking Can Violate Serializability Problem: Given two transaction T9 and T10 T9 : transfers 100 from Y to X T10 : increases the amounts of X and Y by 10% X= X *1.1; Y = Y * 1.1 Initial values : X= 100, Y=400 Solution 1: T9,T10 T9: X = X + 100 = 200; Y= Y – 100 = 300 T10: X=200 * 1.1 =220 Y = 300 * 1.1 = 330 Solution 2: T10, T9 T10: X=100 * 1.1 =110 Y = 400* 1.1 = 440 T9: X = X + 100 = 210; Y= Y – 100 = 340 T9 write_lock(T9, X) T10 begin _transaction read(X) X=X + 100 unlock(T9, X) write(X) X=X * 1.1 write(X) unlock(T10, X) unlock(T9, Y) X=220 read(baly) write_lock(T10, Y) write_lock(T9, Y) X=200 read(X) write_lock(T10, X) unlock(T10, Y) begin _transaction Y=Y * 1.1 write(Y) read(Y) Y=440 commit Y=Y - 100 write(Y) commit Y=340 Locking Can Violate Serializability Findings: • T9, T10: X=220; Y=330 • T10, T9: X=210, Y=340 • Interleaved schedule using R/W locking: X=220; Y=340 • Therefore, interleaved schedule is not serializable What is wrong with the example? T9 write_lock(T9, X) begin _transaction read(X) X=X + 100 unlock(T9, X) write(X) 10 The scheduleTreleases the locks that are held by a transaction as soon as the associated read/write is executed begin _transaction X=200 read(X) write_lock(T10, X) X=X * 1.1 write(balx) unlock(T10, X) X=220 read(Y) Y = Y * 1.1 write_lock(T10, Y) unlock(T10, Y) write_lock(T9, Y) unlock(T9, Y) write(Y) read(Y) Y=440 commit Y = Y- 100 write(Y) commit Y=340 T9 write_lock(T9, X) begin _transaction read(X) X=X+ 100 unlock(T9, X) write(X) T10 However, the transaction itself is locking other items (Y) after it releases its lock on X . _transaction begin X=200 read(X) write_lock(T10, X) X=X * 1.1 write(X) unlock(T10, X) X=220 read(Y) Y=Y* 1.1 write_lock(T10, Y) unlock(T10, baly) write_lock(T9, Y) unlock(T9, Y) write(Y) read(Y) Y=440 commit Y=Y - 100 write(Y) commit Y=340 Two-phase locking (2PL): definition • A transaction follows the two-phase locking protocol, if all locking operations (read_lock, write_lock) precede the first unlock operation in the transaction. T1 begin read-lock(Y) read(Y); write-lock(X) read(X); X:=X+Y; write(X) unlock(Y) unlock(X) commit T9 write_lock(T9, X) begin _transaction T 10 The schedule does not follow 2PL read(X) X=X+ 100 unlock(T9, X) write(X) begin _transaction X=200 read(X) write_lock(T10, X) X=X * 1.1 write(X) unlock(T10, X) X=220 read(Y) Y=Y* 1.1 write_lock(T10, Y) unlock(T10, baly) write_lock(T9, Y) unlock(T9, Y) write(Y) read(Y) Y=440 commit Y=Y - 100 write(Y) commit •A transaction follows the two-phase locking protocol, if all locking operations (read_lock, write_lock) precede the first unlock operation in the transaction. Y=340 Two-phase locking (2PL): definition Two phases: – Growing / Expanding phase: acquires all the locks needed but cannot release any locks – Shrinking phase: releases its existing locks but cannot acquire any new locks T1 begin read-lock(Y) read(Y); } Growing Phase } Shrinking Phase write-lock(X) read(X); X:=X+Y; write(X) unlock(Y) unlock(X) commit 2PL (Basic): Rules • A transaction must acquire a lock on an item before operating on the item. The lock may be read or write depending on the type of access needed. • Once a transaction releases a lock, it can never acquire any new locks. Upgrading/Downgrading locks with 2PL • Upgrading of locks (from read-locked to write-locked) must be done during the expanding phase. • Downgrading of locks (from write-locked to read-locked) must be done in the shrinking phase. Hence, a read_lock(X) operation that downgrades an already held write lock on X can appear only in the shrinking phase. Claims of 2PL 1. If every transaction in a schedule follows the two-phase locking protocol, the schedule is guaranteed to be serializable, obviating the need to test for serializability schedules. 2. If the locking mechanism enforces twophase locking rules, it in effect enforces serializability. 2PL Upholds Serializability T1 T2 T3 It has a cyclic precedence graph; it is not conflict serializable. read_item(X); write_item(X) write_item(X); write_item(X) This schedule becomes (conflict) serializable using 2PL below: T1 T2 write_lock(X); read_item(X); write_lock(X); write_item(X); unlock(X); T3 It has an acyclic precedence graph; it is not conflict serializable. write_item(X); unlock(X); write_lock(X); write_item(X); unlock(X); 2PL Example • Problem – T1 transfers 50 from account A to B – T2 displays the sum of accounts and B – Initial Values: A =100; B=200 T1 T2 DB A=100; B=200 write-lock(B) read(B); B=B-50 write(B) write-lock(A) } Growing Phase B=150 read(A) A:=A+50 write(A) unlock(B) unlock(A) A=150 } Shrinking Phase read-lock(B) read(B) read-lock(A) read(A) display(A+B) unlock(B) unlock(A) } } Growing Phase A+B=300 Shrinking Phase 2-Phase Locking Problem: Given two transaction T1 and T2 T1 adds the content of Y to X; ( X = X+Y) T2 adds the content of X to Y; (Y = Y + X) Initial values : X= 20, Y=30 Solution 1: T1,T2 Solution 2: T2,T1 T1: X = X + Y; 20+30; T2: Y = Y + X; 30+20; X= 50 ; Y=30 X=20; Y=50 T2: Y = Y + X; 30+50; T1: X = X + Y; 20+50; X=50; Y=80 X= 70 ; Y=50 T1 read-lock(Y) read(Y); write-lock(X) unlock(Y) read(X); X:=X+Y; write(X) unlock(X) T2 } read-lock(X) read(X); write-lock(Y) DB } } } X=20; Y=30 Growing Phase unlock(X) read(Y) Y=Y+X write(Y) Shrinking Phase unlock(Y) Unlock instructions do not need to appear at the end of the transactions T1 T2 DB X=20; Y=30 read-lock(Y) read(Y); write-lock(X) read(X); X:=X+Y; write(X) unlock(Y) unlock(X) } } read-lock(X) read(X); write-lock(Y) Growing Phase read(Y) Y=Y+X write(Y) } unlock(X) unlock(Y) } Shrinking Phase Deadlocks may occur 2PL Allows Lock Conversions read_lock(A); read_item(A); read_lock(B); read_item(B); A:= A+B read_lock(C); read_item(C); A:= A+C; . . read_lock(Z); read_item(Z); write_lock(A); A:= A+Z; write(A); unlock(A); . . *upgrade Concurrency Problems Lost update problem Time T1 T2 balx t1 begin _transaction 100 t2 begin _transaction read(balx) 100 t3 read(balx) balx=balx + 100 100 t4 balx=balx - 10 write(balx) 200 t5 write(balx) t6 commit commit 90 90 Solution: Prevent T1 from reading the value of balx until after T2‘s update has been completed. balx should be 190. Preventing the lost update problem with 2PL Time T1 t1 t2 T2 begin _transaction begin _transaction balx 100 write_lock(balx) 100 t3 write_lock(balx) read (balx) 100 t4 wait balx=balx +100 100 t5 wait write (balx) 200 t6 wait t7 read (balx) 200 t8 balx=balx - 10 200 t9 write (balx) 190 t10 commit/unlock(balx) 190 Commit/unlock(balx) 200 Solution: Prevent T1 from reading the value of balx until after T2‘s update has been completed. Concurrency Problems Uncommitted dependency problem Time T3 T4 balx t1 t2 t3 begin _transaction read(balx) balx=balx + 100 100 100 100 write(balx) … rollback 200 200 100 t4 t5 t6 begin _transaction read(balx) balx=balx - 10 t7 t8 write(balx) commit 190 190 Solution: Prevent T3 from reading the value of balx until after the decision has been made to either commit or abort T4‘s effects; balx should be 90 since T4 failed. Preventing the uncommitted dependency problem with 2PL Time T3 t1 T4 begin _transaction balx 100 t2 write_lock(balx) 100 t3 read (balx) 100 balx=balx +100 100 write (balx) 200 t4 begin _transaction t5 write_lock(balx) t6 wait t7 read (balx) 100 t8 balx=balx - 10 100 t9 write (balx) 90 t10 commit/unlock(balx) 90 rollback/unlock(balx) 100 Solution: Prevent T3 from reading the value of balx until after the decision has been made to either commit or abort T4‘s effects Concurrency Problems : Inconsistent Analysis problem Time T5 T6 balx baly balz t1 begin _transaction 100 50 25 sum = 0 100 50 25 0 t2 begin _transaction sum t3 read(balx) read(balx) 100 50 25 0 t4 balx=balx - 10 sum = sum + balx 100 50 25 100 t5 write(balx) read(baly) 90 50 25 100 t6 read(balz) sum = sum + baly 90 50 25 150 t7 balz=balz + 10 90 50 25 150 t8 write(balz) 90 50 35 150 read(balz) 90 50 35 150 sum = sum + balz 90 50 35 185 90 50 35 185 t9 t10 t11 commit commit Solution: Prevent T6 from reading the values of balx and balz until after T5 has completed its updates. Correct result: balx=90, baly =50, balz =35, sum=175 Preventing the inconsistent analysis problem with 2PL Time T5 t1 t2 T6 begin _transaction begin _transaction sum=0 balx baly balz 100 50 25 100 50 25 0 100 50 25 0 Sum t3 write_lock(balx) t4 read (balx) read_lock(balx) 100 50 25 0 t5 balx=balx - 10 wait 100 50 25 0 t6 write (balx) wait 90 50 25 0 t7 write_lock(balz) wait 90 50 25 0 t8 read (balz) wait 90 50 25 0 t9 balz=balz + 10 wait 90 50 25 0 t10 write (balz) wait 90 50 35 0 Preventing the inconsistent analysis problem with 2PL Time balx baly balz Sum wait 90 50 35 0 t12 read (balx) 90 50 35 0 t13 sum=sum+ balx 90 50 35 90 t14 read_lock(baly) 90 50 35 90 t15 read (baly) 90 50 35 90 t16 sum=sum+ baly 90 50 35 140 t17 read_lock(balz) 90 50 35 140 t18 read (balz) 90 50 35 140 t19 sum=sum+ balz 90 50 35 175 90 50 35 175 t11 t20 T5 Commit/unlock(balx , balz) T6 Commit/unlock(balx , baly balz) Why 2PL may reduce concurrency T1 T2 DB X=20; Y=30 read-lock(Y) read(Y); write-lock(X) write-lock(Y) read(X); read(Y) X:=X+Y; Y=Y+100 write(X) write(Y) unlock(Y) unlock(Y) T2 waits even though T1 finishes reading Y unlock(X) •Holding lock unnecessarily, or locking too early: –Transaction T1 may not be able to release item Y after it is through using it if T1 must lock an additional item X later on; –or conversely, T1 must lock the additional item X before it needs it so that it can release Y. T1 Why 2PL may reduce concurrency T2 DB X=20; Y=30 read-lock(Y) read(Y); write-lock(X) write-lock(Y) read(X); read(Y) X:=X+Y; Y=Y+100 write(X) write(Y) unlock(Y) unlock(Y) unlock(X) •Penalty to other transactions: –Another transaction T2 seeking to access Y may be forced to wait, even though T1 is done with Y; –conversely, if X is locked earlier than it is needed, another transaction seeking to access X is forced to wait even though T is not using X yet Variations of 2PL • • • • Basic Conservative Strict Rigorous Conservative 2PL (static 2PL) • Requires a transaction to lock all the items it accesses before the transaction begins execution, by predeclaring its read-set and write-set. (The read-set of a transaction is the set of all items that the transaction reads, and the write-set is the set of all items that it writes) • If any of the predeclared items needed cannot be locked, the transaction does not lock any item; instead, it waits until all the items are available for locking. Conservative 2PL (static 2PL) T1 T2 DB X=20; Y=30 read-lock(Y) write-lock(X) } lock all the items read(Y); write-lock(Y) read(X); read(Y) X:=X+Y; Y=Y+100 write(X) write(Y) unlock(Y) unlock(Y) unlock(X) Conservative 2PL (static 2PL) • POLICY – lock all that you need before reading or writing. Transaction is in shrinking phase after it starts • PROPERTY – Conservative 2PL is a deadlock-free protocol • PRACTICAL – difficult to use because of difficulty predeclaring the read-set and write-set. Strict 2PL • It is the most popular variation of 2PL; it guarantees strict schedules. • A transaction T does not release any of its exclusive (write) locks until after it commits or aborts. Hence, no other transaction can read or write an item that is written by T unless T has committed, leading to a strict schedule for recoverability. Strict 2PL T1 T2 DB X=20; Y=30 read-lock(Y) read(Y); write-lock(X) write-lock(Y) read(X); read(Y) X:=X+Y; Y=Y+100 write(X) write(Y) unlock(Y) commit commit unlock(Y) unlock(x) Strict 2PL • Policy – release write locks only after terminating. Transaction is in expanding/growing phase until it ends (may release some read locks before commit). • Property – NOT a deadlock-free protocol • PRACTICAL – Possible to enforce and desirable due to recoverability Rigorous 2PL • A transaction T does not release any of its locks (exclusive or shared) until after it commits or aborts • Behaves similar to Strict 2PL except it is more restrictive, but easier to implement since all locks are held till commit. Rigorous 2PL T1 T2 DB X=20; Y=30 read-lock(Y) read(Y); write-lock(X) write-lock(Y) read(X); read(Y) X:=X+Y; Y=Y+100 write(X) write(Y) commit commit unlock(X) unlock(Y) unlock(Y) Limitations of 2PL 1. 2PL protocol guarantees serializability (that is, every schedule that is permitted is serializable), but it does not permit all possible serializable schedules (that is, some serializable schedules will be prohibited by the protocol). 2. Use of locks can cause two additional problems: deadlock and starvation. Equivalent serial schedule(S’) Original schedule(S) T1 through swapping T2 begin _transaction T1 T2 begin _transaction read(A) read(A) write(A) write(A) begin _transaction read(A) write(A) begin _transaction read(B) write(B) read(B) read(A) write(B) write(A) commit commit read(B) read(B) write(B) write(B) commit commit Original serializable schedule(S) T1 T2 begin _transaction T1 T2 begin _transaction write-lock(A) read(A) write(A) read(A) begin _transaction write(A) write-lock(B) begin _transaction read(A) write(A) read(B) read(B) write(B) unlock(A) unlock(B) read(A) write(B) write(A) commit commit read(B) read(B) write(B) write(B) commit commit Problems with 2PL • Deadlock • Livelock / Starvation • Cascading rollback Problems with 2PL • Deadlock • Livelock / Starvation • Cascading rollback Deadlock: Example • Problem: – T1 adds the content of Y to X; X=X+Y – T2 adds the content of X to Y; Y=Y+X Deadlock: Example T1 T2 add the content add the content of Y to X of X to Y read_lock(Y); read_item(Y); write_lock(X); X=X+Y write(X) unlock(X) unlock(Y) read_lock(X) read_item(X); write_lock(Y) Y=Y+X write(Y) unlock(X) unlock(Y) Status initial values: X=20, Y =30 Request will be denied since X is locked (shared) to T2 Request will be denied since Y is locked (shared) to T1 What is Deadlock? •Deadlock is an impasse that may T1 T2 add the content add the content of Y to X of X to Y result when two (or more) transactions are each waiting for Status locks held by the other to be initial values: released. X=20, Y =30 •It occurs when : –each transaction T in a set of two or more transactions is waiting for some item X, but –X is locked by another transaction T’ in the set. read_lock(Y); read_lock(X) read_item(Y); read_item(X); write_lock(X); write_lock(Y) X=X+Y Y=Y+X write(X) write(Y) unlock(X) unlock(X) •Hence, each transaction in the set is on a waiting unlock(Y) unlock(Y) queue, waiting for one of the other transactions in the set to release the lock on an item. How is Deadlock detected? • Through the construction of wait-for-graph (WFG) showing the transaction dependencies. – Transaction T1 is dependent on T2 if transaction T2 holds the lock on a data item that T1 is waiting for. • Deadlock exists if and only if the wfg contains a cycle. • The deadlock detection algorithm generates wfg at regular intervals and examines it for a cycle – Small interval: increases overhead – Large interval: deadlock may not de detected for a long period. Deadlock Detection Wait-for graph: showing deadlock Create a node for each transaction. •Create a directed edge T1 T2, if transaction T1 is waiting to lock an item that is currently locked by T2 •Deadlock exists if and only if the wfg contains a cycle. y T1 T2 x T1 T2 add the content add the content of Y to X of X to Y Status initial values: X=20, Y =30 read_lock(Y); read_item(Y); read_lock(X) read_item(X); write_lock(Y) write_lock(X); T2 is waiting to lock Y, which is currently locked by T1; (T2T1) T1 is waiting to lock X, which is currently locked by T2; (T1T2) x T1 y T2 Time T17 T18 t1 begin _transaction t2 write_lock(balx) t3 read (balx) write_lock(baly) t4 balx=balx - 10 read (baly) t5 write (balx) baly=baly + 100 t6 write_lock(baly) write (baly) t7 wait write_lock(balx) t8 wait wait t9 wait wait t10 …. t11 ….. begin _transaction wait ….. Deadlock: example x T17 y T18 How is deadlock solved? T17 T18 t1 begin _transaction t2 write_lock(balx) t3 read (balx) write_lock(baly) t4 balx=balx - 10 read (baly) t5 write (balx) baly=baly + 100 t6 write_lock(baly) write (baly) t7 wait write_lock(balx) t8 wait wait t9 wait wait t10 …. t11 ….. •Break deadlock by aborting one or more of the transactions begin _transaction wait ….. •Abort transaction T18 •Locks held by T18 are released •Transaction T17 can continue and finish •DBMS restarts T18 How is Deadlock Handled? • Deadlock prevention – The DBMS looks ahead to determine if a transaction would cause deadlock and never allows deadlock to occur. • Deadlock detection and recovery – The DBMS allows deadlock to occur but recognizes occurrences of deadlock and breaks it. Deadlock Prevention 1. 2. 3. 4. 5. 6. Use of Conservative Locking Ordering of all items in the database … Use of transaction timestamp No waiting Cautious waiting Use of timeouts Deadlock Prevention Use of Conservative Locking T17 T18 begin _transaction •Every transaction locks all the items it needs in advance (generally not a practical assumption) write_lock(X) write_lock(Y) begin _transaction read (X) write_lock(Y) X=X - 10 write_lock(X) write (X) read (Y) … unlock(X) Y=Y + 100 unlock(Y) write (Y) … unlock(Y) unlock(X) •If any of the items cannot be obtained, none of the items are locked. Rather, the transaction waits and then tries again to lock all the item it needs. Review: Conservative 2PL (static 2PL) • Requires a transaction to lock all the items it accesses before the transaction begins execution, by predeclaring its read-set and write-set. (The read-set of a transaction is the set of all items that the transaction reads, and the write-set is the set of all items that it writes) • If any of the predeclared items needed cannot be locked, the transaction does not lock any item; instead, it waits until all the items are available for locking. Deadlock Prevention Ordering of all items in the database… T17 T18 begin _transaction write_lock(X) begin _transaction read (X) write_lock(X) X=X - 10 read (X) write (X) X=X+ 100 write_lock(Y) write (Y) write_lock(Y) write (Y) … … X Y Z •Ordering all the items in the database and making sure that a transaction that needs several items will lock them according to that order. •However, this requires that the programmer is aware of the chosen order of the items, which is not very practical Deadlock Prevention No Waiting • In case of inability to obtain a lock, a transaction aborts and is resubmitted with a fixed delay. (causes too many needless aborts) Deadlock Prevention Cautious Waiting Suppose that transaction Ti tries to lock an item X but is not able to do so because X is locked by some other transaction Tj with a conflicting lock. (Ti Tj) Cautious waiting: if Tj is not blocked (not waiting for some other locked item) then Ti is blocked and allowed to wait else abort Ti That is, if Ti is waiting for Tj, let Ti wait unless Tj is also waiting for Tz to release some other item. Deadlock Prevention Cautious Waiting Time t1 Ti Tj begin _transaction t2 write_lock(balx) begin _transaction t3 read (balx) write_lock(baly) t4 balx=balx - 10 read (baly) t5 write (balx) baly=baly + 100 t6 write_lock(baly) write (baly) t7 wait …. t8 wait t9 wait Since Tj is not blocked (not waiting for some other locked item) then Ti is blocked and allowed to wait Deadlock Prevention Cautious Waiting Time t1 Ti Tj begin _transaction t2 write_lock(balx) begin _transaction t3 read (balx) write_lock(baly) t4 balx=balx - 10 read (baly) t5 write (balx) baly=baly + 100 t6 write_lock(baly) write (baly) t7 abort write_lock(Z) t8 wait t9 wait Since Tj is blocked (waiting for some other locked item) Tk then abort Ti begin _transaction write_lock(Z) Deadlock Prevention Use of Timeouts • Practical because of its low overhead and simplicity. • If a transaction waits for a period longer than a system-defined timeout period, the system assumes that the transaction may be deadlocked and aborts it – regardless of whether a deadlock actually exists or not. • DISADVANTAGE: Some transactions that were not deadlocked may abort and may have to be resubmitted. Deadlock Prevention Use of transaction timestamp • Use of a transaction timestamp TS(T), which is a unique identifier assigned to each transaction. • The timestamps are typically ordered based on the order in which transactions are started; hence, if T1 starts before transaction T2, then TS(T1) < TS(T2) • The older transaction T1 has the smaller timestamp value Deadlock Prevention Use of transaction timestamp Time t1 Ti Tj begin _transaction t2 write_lock(balx) begin _transaction t3 read (balx) write_lock(baly) t4 balx=balx - 10 read (baly) t5 write (balx) baly=baly + 100 t6 write_lock(baly) write (baly) t7 wait …. t8 wait t9 wait TS(Ti) = t1 TS(Tj) = t2 Ti = older Tj = younger TS(Ti)< TS(Tj) Two Schemes of Deadlock Prevention • Wait-die • Wound-wait Case: Suppose the transaction Ti tries to lock an item X, but is not able to because X is locked by some other transaction Tj with a conflicting lock. Ti Tj , therefore Ti is waiting for Tj Two Schemes of Deadlock Prevention Wait-Die : Ti Tj The rules of wait-die are as follows: if TS(Ti) < TS(Tj) then (Ti older than Tj) Ti is allowed to wait else (Ti younger than Tj) abort Ti (Ti dies) and restart it later with the same timestamp • Older transactions producing deadlock waits on younger transaction to get the locked items held by it. • Younger transaction producing deadlock gives up the wait and aborts (dies), then gets resubmitted. Wait-Die : Ti Tj Time Ti Tj t1 begin _transaction t2 write_lock(balx) t3 read (balx) write_lock(baly) t4 balx=balx - 10 read (baly) t5 write (balx) baly=baly + 100 t6 write_lock(baly) write (baly) t7 wait …. t8 t9 wait wait begin _transaction TS(Ti) = t1 TS(Tj) = t2 Ti = older Tj = younger Ti is allowed to wait until Tj releases the lock / commits Wait-Die : Ti Tj Time Ti t1 Tj begin _transaction t2 begin _transaction t3 write_lock(balx) read (baly) t4 read (balx) baly=baly + 100 t5 balx=balx - 10 write (baly) t6 write (balx) t7 write_lock(baly) t8 abort t9 t10 write_lock(baly) …. TS(Ti) = t2 TS(Tj) = t1 Ti = younger Tj = older Abort Ti restart it later with the same timestamp Two Schemes of Deadlock Prevention Wound-Wait: Ti Tj The rules of wound-wait are as follows: If TS(Ti) < TS(Tj) Then (Ti older than Tj) abort Tj (Ti wounds Tj) and restart it later with the same timestamp Else (Ti younger than Tj) Ti is allowed to wait • Younger transaction producing deadlock allowed to wait for older one to release locked item • Older transaction producing deadlock preempts the younger transaction by wounding (killing) it and causing it to abort. Wound-Wait: Ti Tj Time Ti Tj t1 begin _transaction t2 write_lock(balx) begin _transaction t3 read (balx) write_lock(baly) t4 balx=balx - 10 read (baly) t5 write (balx) baly=baly + 100 t6 write_lock(baly) write (baly) t7 …. abort /rollback TS(Ti) = t1 TS(Tj) = t2 Ti = older Tj = younger Tj aborted and rolled back; restarted later with the same timestamp Wound-Wait: Ti Tj Time Ti t1 Tj begin _transaction t2 begin _transaction t3 write_lock(balx) read (baly) t4 read (balx) baly=baly + 100 t5 balx=balx - 10 write (baly) t6 write (balx) t7 write_lock(baly) t8 wait t9 t10 write_lock(baly) …. TS(Ti) = t2 TS(Tj) = t1 Ti = younger Tj = older Ti is allowed to wait Two Schemes of Deadlock Prevention Wait-Die and Wound-Wait Both schemes kill younger transactions involved in a deadlock. Wait-die: transactions only wait on younger transactions Wound-wait: transactions only wait on older transactions Both schemes are deadlock-free. Problems with 2PL • Deadlock • Livelock / Starvation • Cascading rollback Livelock/Starvation 1. A transaction is starved if it cannot proceed for an indefinite period of time while other transactions in the system continue normally. This may occur if the waiting scheme for locked items is unfair, giving priority to some transactions over others. Livelock/Starvation 2. Starvation can only occur in the algorithms for dealing with deadlock. It occurs if the algorithms select the same transaction as victim repeatedly, thus causing it to abort and never finish execution. Remedies for Preventing Starvation 1. First-come-first-serve queue • • a fair waiting scheme; transactions are enabled to lock an item in the order in which they are originally requested to lock the item. 2. Allow some transactions to have priority over others but increase the priority of a transaction the longer it waits, until it eventually gets the highest priority and proceeds. Remedies for Preventing Starvation 3. The victim selection algorithm can use higher priorities for transactions that have been aborted multiple times so that they are not selected as victims repeatedly. The wait-die and wound-wait schemes avoid starvation. Problems with 2PL • Deadlock • Livelock / Starvation • Cascading rollback Problems with 2PL Cascading Rollback • Cascading rollback occurs when a single transaction leads to a series of rollbacks. • Cascading rollbacks are undesirable since they potentially lead to the undoing of a significant amount of work Cascading rollback in 2PL Time t1 T14 begin _transaction t2 write_lock(balx) t3 read (balx) t4 read_lock(baly) t5 read (baly) t6 balx=baly + balx t7 write (balx) t8 unlock (balx) t9 t10 T15 .. .. .. begin _transaction write_lock(balx) read (balx) T16 •Since T16Cascading is dependentrollback on T15 (itin has2PL read an item updated Time by TT1514), then T16 should T15 be rolled back T16 t11 t12 t13 t14 t15 t16 t17 t18 t19 .. . .. .. .. .. abort/rollback . balx=balx+ 100 write (balx) unlock (balx) .. .. .. .. .. rollback . . begin _transaction read_lock(balx) rollback.. . •Since T15 is dependent on T14 (it has read an item updated by T14 ), then T15 should be rolled back Cascading rollback in 2PL • Cascading rollback happens when a single transaction leads to a series of rollback. Failure (and rollback) of T14 results in T15 and T16 being rolled back How to prevent cascading rollbacks? • Leave the release of all locks until the end of the transaction (rigorous 2PL). • This prevents other transactions to read values of items whose transactions have not yet committed.