We will be analyzing schedules of transactions in a system that uses some form of timestamp-based concurrency control.
In each exercise, there are three transactions (T1, T2 and T3) and three data items (X, Y and Z).
You should assume that:
The read and write timestamps of all of the data items are initially 0.
The timestamps assigned to the transactions are:
These timestamps are consistent with the fact that, in the schedules we’ll be analyzing below, T1 starts first, followed by T2, followed by T3.
In giving your answers, you should fill in a table that begins as follows:
| request | response | state changes and/or explanation |
|---|---|---|
| r1(Y) | allowed | RTS(Y) = 100 |
The third column should include any changes to the state maintained for the data item. If a request is denied or ignored, that column should also include a brief explanation of why.
You do not need to restart a transaction that is rolled back, which means that you can skip any requests by a transaction that come after the point at which it is rolled back.
In this exercise, we will assume that the DBMS is using timestamp-based concurrency control with commit bits and with only one version of each data item.
What is the purpose of maintaining commit bits?
Consider the following schedule:
s1; r1(Y); s2; w2(Y); w2(X); s3; r3(Z); r2(Z); w3(Y); r3(X); c2; c3; w1(Y); r1(X); c1
How would the system respond to each of the requested actions?
In addition to the assumptions mentioned in the preliminaries, you should assume that all of the commit bits are initially true.
Make sure to include the responses to the commit requests (c1, c2, c3), since they are relevant when a system uses commit bits.
If a transaction is made to wait, you should include the relevant request a second time when the transaction is allowed to try again.
| request | response | state changes and/or explanation |
|---|---|---|
| r1(Y) | allowed | RTS(Y) = 100 |
| w2(Y) | allowed | WTS(Y) = 200, c(Y) = false |
| w2(X) | allowed | WTS(X) = 200, c(X) = false |
| r3(Z) | allowed | RTS(Z) = 300 |
| r2(Z) | allowed | RTS is not changed (see below) |
| w3(Y) | allowed | WTS(Y) = 300, C(Y) remains false |
| r3(X) | denied; make wait | TS(T3) >= WTS(X) but c(X) == false |
| c2 | allowed | c(X) = true |
| r3(X) | allowed! | RTS(X) = 300 |
| c3 | allowed | c(Y) = true |
| w1(Y) | ignored | TS(T1) >= RTS(Y) but TS(T1) < WTS(Y) |
| and c(Y) == true | ||
| r1(X) | denied; roll back | TS(T1) < WTS(X); RTS(Y) = 0 |
| c1 | doesn’t happen | T1 has already been rolled back |
Here are some additional notes about each request:
r1(Y):
w2(Y):
w2(X):
r3(Z):
r2(Z):
w3(Y):
r3(X):
c2: T2 commits
r3(X): now that c(X) is true, T3 is allowed to try again and the read is allowed.
c3: T3 commits.
w1(Y):
r1(X):
c1: T1 has already been rolled back, so this action doesn’t occur.
In this exercise, we will assume that the DBMS is using timestamp-based concurrency control without commit bits and with multiple versions of each item.
What is the purpose of maintaining multiple versions?
Consider the following schedule (which is slightly different than the one from Exercise 1):
s1; r1(Y); s2; w2(Y); w2(X); s3; r3(Z); r2(Z); w3(Y); r3(X); c2; c3; r1(X); w1(Z); c1
How would the system respond to each of the requested actions?
You should make the same assumptions as before about the timestamps of the transactions and the initial timestamps of the data items.
Make sure to create a new version of a data item whenever necessary.
Because commits don’t have an effect when we’re not using
commit bits, you do not need to include the commit actions
(c1, c2, etc.) in your table.
| request | response | state changes and/or explanation |
|---|---|---|
| r1(Y) | allowed to read Y(0) | RTS(Y(0)) = 100 |
| w2(Y) | allowed | create Y(200) with RTS = 0 |
| w2(X) | allowed | create X(200) with RTS = 0 |
| r3(Z) | allowed to read Z(0) | RTS(Z(0)) = 300 |
| r2(Z) | allowed to read Z(0) | RTS(Z(0)) is unchanged |
| w3(Y) | allowed | create Y(300) with RTS = 0 |
| r3(X) | allowed to read X(200) | RTS(X(200)) = 300 |
| r1(X) | allowed to read X(0) | RTS(X(0)) = 100 |
| w1(Z) | denied; rollback | RTS(X(0)) = 0; RTS(Y(0)) = 0 |
Here are some additional notes about each request:
r1(Y):
w2(Y):
w2(X):
r3(Z):
r2(Z):
w3(Y):
r3(X):
r1(X):
w1(Z):
Assume that:
Consider the following schedule involving the transactions T1, T2, and T3:
r1(X); r1(Z); w2(Y); w2(X); r3(Z); w3(Y); w1(Z)
Determine if this schedule would lead to deadlock.
If deadlock occurs, show the partial schedule in table form (including lock operations and any commits) up to the point of deadlock, along with the waits-for graph at the point of deadlock.
If deadlock does not occur, show the full schedule, including lock operations and commits. In that case, you do not need to include the waits-for graph.
In either case, your schedule should include any changes to the sequence of operations that occur because a transaction is forced to wait for a lock.
If two transactions wait for a lock held by the same other transaction, and that other transaction subsequently commits, you should assume that the waiting transaction with the smaller transaction number is granted its request first.
The schedule would lead to deadlock.
Here is the partial schedule in table form:
|
T1 |
T2 |
T3 |
|---|---|---|
|
sl(X); r(X) |
|
|
Here is the waits-for graph at the point of deadlock:

Explanation
r1(X): T1 requests and acquires a shared lock for X and reads X.
r1(Z): T1 requests and acquires a shared lock for Z and reads Z.
w2(Y): T2 requests and acquires an exclusive lock for Y and writes Y.
w2(X): T2 requests an exclusive lock for X, but T1 already holds a shared lock for X, so the request is denied and T2 is made to wait for T1. Add a directed edge from T2 to T1 in the waits-for graph.
r3(Z): T3 requests a shared lock for Z. T1 already holds a shared lock for Z, but multiple transactions are allowed to hold shared locks for the same data element, and thus T3 acquires the lock and reads Z.
w3(Y): T3 requests an exclusive lock for Y, but T2 already holds an exclusive lock for Y, so the request is denied and T3 is made to wait for T2. Add a directed edge from T3 to T2 in the waits-for graph.
w1(Z): T1 attempts to upgrade its shared lock for Z to an exclusive lock, but T3 also holds a shared lock for Z, and thus the request is denied and T1 is made to wait for T3. Adding a directed edge from T1 to T3 in the waits-for graph creates a cycle: T1 → T3 → T2 → T1.
The DBMS would detect the cycle in the waits-for graph and conclude that the three transactions are deadlocked. The DBMS would then abort and restart one of the transactions so that the others could make progress.
Depending on the transaction chosen to be aborted and restarted and when it is restarted, it’s possible that additional conflicts could occur, and even that deadlock could occur once again.
Now imagine that we change the final action in the schedule to
w1(X):
r1(X); r1(Z); w2(Y); w2(X); r3(Z); w3(Y); w1(X)
How would that change your answer?
Deadlock would no longer occur.
Here is the full schedule in table form:
|
T1 |
T2 |
T3 |
|---|---|---|
|
sl(X); r(X) |
|
|
Explanation
Steps a-f are the same as before.
w1(X): T1 attempts to upgrade its shared lock for X to an exclusive lock. Since no one else has any locks for X, T1 is able to upgrade to an exclusive lock and write X.
T1 is now done, so it commits. And because the DBMS is using rigorous locking, T1 releases all of its locks at commit, which we show by putting the unlock actions after the commit action.
w2(X): Now that T1 has released its lock for X, T2 can try again to acquire an exclusive lock for X. Since no one has any locks on X, T2 can acquire the exclusive lock and write X.
T2 is now done, so it commits and releases its locks.
w3(Y): Now that T2 has released its lock for Y, T3 can try again to acquire an exclusive lock for Y. Since no one has any locks on Y, T3 can acquire the exclusive lock and write Y.
T3 is now done, so it commits and releases its locks.
Note that the need to wait for locks has modified the order of some of the actions. The final schedule is:
r1(X); r1(Z); w2(Y); r3(Z); w1(X); w2(X); w3(Y)
Last updated on November 3, 2025.