DBMS Module 5
DBMS Module 5
Module 5
Deadlock occurs when each transaction T in a set of two or more transactions is waiting for some item that is
locked by some other transaction T′ in the set. Hence, each transaction in the set is in a waiting queue,
waiting for one of the other transactions in the set to release the lock on an item. But because the other
transaction is also waiting, it will never release the lock.
A simple example is shown in Figure 21.5(a), where the two transactions T1′ and T2′ are deadlocked in a
partial schedule; T1′ is in the waiting queue for X, which is locked by T2′, whereas T2′ is in the waiting queue
for Y, which is locked by T1′. Meanwhile, neither T1′ nor T2′ nor any other transaction can access items X and
Y.
• One deadlock prevention protocol, which is used in conservative two-phase locking, requires that
every transaction lock all the items it needs in advance (which is generally not a practical
assumption)—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 items it needs. Obviously, this solution further
limits concurrency.
• A second protocol, which also limits concurrency, involves ordering all the items in the database and
making sure that a transaction that needs several items will lock them according to that order. This
requires that the programmer (or the system) is aware of the chosen order of the items, which is
also not practical in the database context.
A number of other deadlock prevention schemes have been proposed that make a decision about what to
do with a transaction involved in a possible deadlock situation:
The timestamps are typically based on the order in which transactions are started; hence, if transaction T1
starts before transaction T2, then TS(T1) < TS(T2). Notice that the older transaction (which starts first) has
the smaller timestamp value. Two schemes that prevent deadlock are called wait-die and wound-wait.
Suppose that 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. The rules followed by these schemes are:
Wait-die. If TS(Ti) < TS(Tj), then (Ti older than Tj) Ti is allowed to wait; otherwise (Ti younger than Tj) abort
Ti (Ti dies) and restart it later with the same timestamp.
In wait-die, an older transaction is allowed to wait for a younger transaction, whereas a younger transaction
requesting an item held by an older transaction is aborted and restarted.
Wound-wait. If TS(Ti) < TS(Tj), then (Ti older than Tj) abort Tj (Ti wounds Tj) and restart it later with the
same timestamp; otherwise (Ti younger than Tj) Ti is allowed to wait.
The wound-wait approach does the opposite: A younger transaction is allowed to wait for an older one,
whereas an older transaction requesting an item heldby a younger transaction preempts the younger
transaction by aborting it.
Both schemes end up aborting the younger of the two transactions (the transaction that started later) that
may be involved in a deadlock, assuming that this will waste less processing. It can be shown that these two
techniques are deadlock-free, since in waitdie, transactions only wait for younger transactions so no cycle is
created. Similarly, in wound-wait, transactions only wait for older transactions so no cycle is created.
However, both techniques may cause some transactions to be aborted and restarted needlessly, even
though those transactions may never actually cause a deadlock.
Another group of protocols that prevent deadlock do not require timestamps. These include the no waiting
(NW) and cautious waiting (CW) algorithms.
In the no waiting algorithm, if a transaction is unable to obtain a lock, it is immediately aborted and then
restarted after a certain time delay without checking whether a deadlock will actually occur or not. In this
case, no transaction ever waits, so no deadlock will occur. However, this scheme can cause transactions to
abort and restart needlessly.
The cautious waiting algorithm was proposed to try to reduce the number of needless aborts/restarts.
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. The cautious waiting rule is as follows:
■ Cautious waiting. If Tj is not blocked (not waiting for some other locked item), then Ti is blocked and
allowed to wait; otherwise abort Ti.
Deadlock Detection.
An alternative approach to dealing with deadlock is deadlock detection, where the system checks if a state
of deadlock actually exists. This solution is attractive if we know there will be little interference among the
transactions—that is, if different transactions will rarely access the same items at the same time. This can
happen if the transactions are short and each transaction locks only a few items, or if the transaction load is
light. On the other hand, if transactions are long and each transaction uses many items, or if the transaction
load is heavy, it may be advantageous to use a deadlock prevention scheme. A simple way to detect a state
of deadlock is for the system to construct and maintain a wait-for graph. One node is created in the wait-for
graph for each transaction that is currently executing. Whenever a transaction Ti is waiting to lock an item X
that is currently locked by a transaction Tj, a directed edge (Ti → Tj) is created in the wait-for graph. When Tj
releases the lock(s) on the items that Ti was waiting for, the directed edge is dropped from the wait-for
graph. We have a state of deadlock if and only if the wait-for graph has a cycle.
Starvation. Another problem that may occur when we use locking is starvation, which occurs when a
transaction 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 in that it gives priority to some
transactions over others.
One solution for starvation is to have a fair waiting scheme, such as using a first-come-first-served queue;
transactions are enabled to lock an item in the order in which they originally requested the lock. Another
scheme allows some transactions to have priority over others but increases the priority of a transaction the
longer it waits, until it eventually gets the highest priority and proceeds.
Starvation can also occur because of victim selection if the algorithm selects the same transaction as victim
repeatedly, thus causing it to abort and never finish execution. The algorithm can use higher priorities for
transactions that have beenaborted multiple times to avoid this problem.
A timestamp is a unique identifier created by the DBMS to identify a transaction. Typically, timestamp
values are assigned in the order in which the transactions are submitted to the system, so a timestamp can
be thought of as the transaction start time. The timestamp of transaction T is refered as TS(T).
Concurrency control techniques based on timestamp ordering do not use locks; hence, deadlocks cannot
occur.
In timestamp ordering, the schedule is equivalent to the particular serial order corresponding to the order of
the transaction timestamps. The algorithm allows interleaving of transaction operations, but it must ensure
that for each pair of conflicting operations in the schedule, the order in which the item is accessed must
follow the timestamp order. To do this, the algorithm associates with each database item X two timestamp
(TS) values:
1. read_TS(X). The read timestamp of item X is the largest timestamp among all the timestamps of
transactions that have successfully read item X—that is, read_TS(X) = TS(T), where T is the youngest
transaction that has read X successfully.
2. write_TS(X). The write timestamp of item X is the largest of all the timestamps of transactions that have
successfully written item X—that is, write_TS(X) = TS(T), where T is the youngest transaction that has written
X successfully. Based on the algorithm, T will also be the last transaction to write item X, as we shall see.
If T is aborted and rolled back, any transaction T1 that may have used a value written by T must also be
rolled back. Similarly, any transaction T2 that may have used a value written by T1 must also be rolled back,
and so on. This effect is known as cascading rollback and is one of the problems associated with basic TO,
since the schedules produced are not guaranteed to be recoverable.
The concurrency control algorithm must check whether conflicting operations violate the timestamp
ordering in the following two cases:
Strict Timestamp Ordering (TO). A variation of basic TO called strict TO ensures that the schedules are
both strict (for easy recoverability) and (conflict) serializable. In this variation, a transaction T issues a
read_item(X) or write_item(X) such that TS(T) > write_TS(X) has its read or write operation delayed until the
transaction T′ that wrote the value of X (hence TS(T′) = write_TS(X)) has committed or aborted.
To implement this algorithm, it is necessary to simulate the locking of an item X that has been written by
transaction T′ until T′ is either committed or aborted. This algorithm does not cause deadlock, since T waits
for T′ only if TS(T) > TS(T′).
Thomas’s Write Rule. A modification of the basic TO algorithm, known as Thomas’s write rule, does
not enforce conflict serializability, but it rejects fewer write operations by modifying the checks for the
write_item(X) operation as follows:
1. If read_TS(X) > TS(T), then abort and roll back T and reject the operation.
2. If write_TS(X) > TS(T), then do not execute the write operation but continue processing. This is because
some transaction with timestamp greater than TS(T)—and hence after T in the timestamp ordering—has
already written the value of X. Thus, we must ignore the write_item(X) operation of T because it is already
outdated and obsolete. Notice that any conflict arising from this situation would be detected by case (1).
3. If neither the condition in part (1) nor the condition in part (2) occurs, then execute the write_item(X)
operation of T and set write_TS(X) to TS(T).
1. If there is catastrophic failure, such as a disk crash, the recovery method restores a past copy of
the database that was backed up.
2. For noncatastrophic failure, the recovery protocol does not need a complete archival copy of the
database. Rather, the entries kept in the online system log on disk are analyzed to determine the
appropriate actions for recovery.
Two main policies for recovery from non catastrophic transaction failures: deferred update and immediate
update.
• The deferred update techniques do not physically update the database on disk until after a transaction
commits; then the updates are recorded in the database. Before reaching commit, all transaction
updates are recorded in main memory buffers that the DBMS maintains. Before commit, the updates
are recorded persistently in the log file on disk, and then after commit, the updates are written to the
database from the main memory buffers.
If a transaction fails before reaching its commit point, it will not have changed the database on disk in
any way, so UNDO is not needed. It may be necessary to REDO the effect of the operations of a
committed transaction from the log, because their effect may not yet have been recorded in the
database on disk. Hence, deferred update is also known as the NO-UNDO/REDO
• In the immediate update techniques, the database may be updated by some operations of a
transaction before the transaction reaches its commit point. However, these operations must also be
recorded in the log on disk by force-writing before they are applied to the database on disk, making
recovery still possible. If a transaction fails after recording some changes in the database on disk but
before reaching its commit point, the effect of its operations on the database must be undone or rolled
back. This technique, known as the UNDO/REDO algorithm, requires both operations during recovery
and is used most often in practice.
Associated with each buffer in the cache is a dirty bit, which can be included in the directory entry to indicate
whether or not the buffer has been modified. When a page is first read from the database disk into a cache
buffer, a new entry is inserted in the cache directory with the new disk page address, and the dirty bit is set
to 0 (zero). As soon as the buffer is modified, the dirty bit for the corresponding directory entry is set to 1
(one).
Additional information, such as the transaction id(s) of the transaction(s) that modified the buffer, are also
kept in the directory.
When the buffer contents are replaced (flushed) from the cache, the contents must first be written back to
the corresponding disk page only if its dirty bit is 1.
Another bit, called the pin-unpin bit, is also needed—a page in the cache is pinned (bit value 1 (one)) if it
cannot be written back to disk as yet.
Two main strategies can be employed when flushing a modified buffer back to disk.
• The first strategy, known as in-place updating, writes the buffer to the same original disk location, thus
overwriting the old value of any changed data items on disk. Hence, a single copy of each database
disk block is maintained.
• The second strategy, known as shadowing, writes an updated buffer at a different disk location, so
multiple versions of data items can be maintained, but this approach is not typically used in practice.
In general, the old value of the data item before updating is called the before image (BFIM), and the new
value after updating is called the after image (AFIM). If shadowing is used, both the BFIM and the AFIM can
be kept on disk; hence, it is not strictly necessary to maintain a log for recovering.
Write-Ahead Logging
When in-place updating is used, it is necessary to use a log for recovery. In this case, the recovery mechanism
must ensure that the BFIM of the data item is recorded in the appropriate log entry and that the log entry is
flushed to disk before the BFIM is overwritten with the AFIM in the database on disk. This process is generally
known as write-ahead logging
A REDO-type log entry includes the new value (AFIM) of the item written by the operation since this is needed
to redo the effect of the operation from the log (by setting the item value in the database on
disk to its AFIM). The UNDO-type log entries include the old value (BFIM) of the item since this is needed to
undo the effect of the operation from the log (by setting the item value in the database back to its BFIM)
1. If a cache buffer page updated by a transaction cannot be written to disk before the transaction
commits, the recovery method is called a no-steal approach.
2. On the other hand, if the recovery protocol allows writing an updated buffer before the transaction
commits, it is called steal.
3. If all pages updated by a transaction are immediately written to disk before the transaction
commits, the recovery approach is called a force approach.
4. Otherwise, it is called no-force. The force rule means that REDO will never be needed during
recovery, since any committed transaction will have all its updates on disk before it is committed.
If a transaction T is rolled back, any transaction S that has read the value of some data item X written by T
must also be rolled back. Similarly, once S is rolled back, any transaction R that has read the value of some
data item Y written by S must also be rolled back; and so on. This phenomenon is called cascading rollback,
and it can occur when the recovery protocol ensures recoverable schedules.
Shadow Paging
This is the method where all the transactions are executed in the primary memory or the shadow copy of
database. Once all the transactions completely executed, it will be updated to the database. Hence, if there is
any failure in the middle of transaction, it will not be reflected in the database. Database will be updated after
all the transaction is complete.
A database pointer will be always pointing to the consistent copy of the database, and copy of the database
is used by transactions to update. Once all the transactions are complete, the DB pointer is modified to point
to new copy of DB, and old copy is deleted. If there is any failure during the transaction, the pointer will be
still pointing to old copy of database, and shadow database will be deleted. If the transactions are complete
then the pointer is changed to point to shadow DB, and old DB is deleted.
As we can see in above diagram, the DB pointer is always pointing to consistent and stable database. This
mechanism assumes that there will not be any disk failure and only one transaction executing at a time so
that the shadow DB can hold the data for that transaction. It is useful if the DB is comparatively small
because shadow DB consumes same memory space as the actual DB. Hence it is not efficient for huge DBs.
In addition, it cannot handle concurrent execution of transactions. It is suitable for one transaction at a time
END