Assumptions • Every timestamp value is unique and accurately represents an instant in time. • A higher-valued timestamp occurs later in time than a lower-valued timestamp.
Generating a timestamp A number of different approaches can generate timestamps • Using the value of the system's clock at the start of a transaction as the timestamp. • Using a
thread-safe shared counter that is incremented at the start of a transaction as the timestamp. • A combination of the above two methods.
Formal definition Each transaction (T_i) is an ordered list of actions (A_{ix}). Before the transaction performs its first action (A_{i1}), it is marked with the current
timestamp, or any other
strictly totally ordered sequence: TS(T_i) = NOW(). Every transaction is also given an initially empty set of transactions upon which it depends, DEP(T_i) = [], and an initially empty set of old objects which it updated, OLD(T_i) = []. Each
object (O_j) in the database is given two timestamp fields which are not used other than for concurrency control: • RT(O_j) is the timestamp of the last transaction that read the value of the object ( TS(T_r), where T_r is the last transaction that read the value of the object). • WT(O_j) is the timestamp of the last transaction that updated the value of the object ( TS(T_w), where T_w is the last transaction that updated the value of the object). For all T_i: :For each action A_{ix}: ::If A_{ix} wishes to read the value of O_j: :::If WT(O_j) > TS(T_i) then
abort (a more recent thread has overwritten the value), :::Otherwise update the set of dependencies DEP(T_i).\mathrm{add}(WT(O_j)) and set RT(O_j) = \max(RT(O_j), TS(T_i)); ::If A_{ix} wishes to update the value of O_j: :::If RT(O_j) > TS(T_i) then
abort (a more recent thread is already relying on the old value), :::If WT(O_j) > TS(T_i) then
skip (the
Thomas Write Rule), :::Otherwise store the previous values, OLD(T_i).\mathrm{add}(O_j, WT(O_j)), set WT(O_j) = TS(T_i), and update the value of O_j. :While there is a transaction in DEP(T_i) that has not ended:
wait :If there is a transaction in DEP(T_i) that aborted then
abort :Otherwise:
commit. To
abort: :For each (\mathrm{old}O_j, \mathrm{old}WT(O_j)) in OLD(T_i) ::If WT(O_j) equals TS(T_i) then restore O_j = \mathrm{old}O_j and WT(O_j) = \mathrm{old}WT(O_j)
Informal definition Whenever a transaction initiated, it receives a timestamp. The '''transaction's timestamp''' indicates when the transaction was initiated. These timestamps ensure that transactions affect each object in the same sequence of their respective timestamps. Thus, given two operations that affect the same object from different transactions, the operation of the transaction with the earlier timestamp must execute before the operation of the transaction with the later timestamp. However, if the operation of the wrong transaction is actually presented first, then it is aborted and the transaction must be restarted. Every object in the database has a
read timestamp, which is updated whenever the object's data is read, and a
write timestamp, which is updated whenever the object's data is changed. If a transaction wants to read an object, • but the transaction started
before the object's write timestamp it means that something changed the object's data after the transaction started. In this case, the transaction is canceled and must be restarted. • and the transaction started
after the object's write timestamp, it means that it is
safe to read the object. In this case, if the transaction's timestamp is after the object's read timestamp, the read timestamp is set to the transaction's timestamp. If a transaction wants to write to an object, • but the transaction started
before the object's read timestamp it means that something has had a look at the object, and we assume it took a copy of the object's data. So we can't write to the object as that would make any copied data invalid, so the transaction is aborted and must be restarted. • and the transaction started
before the object's write timestamp it means that something has changed the object since we started our transaction. In this case we use the
Thomas write rule and simply skip our write operation and continue as normal; the transaction does not have to be aborted or restarted • otherwise, the transaction writes to the object, and the object's write timestamp is set to the transaction's timestamp. == Physically unrealizable ==