Transactions, Journalling and Recovery

Transactions, Journalling and Recovery

There is a little-discussed topic in many books on object-oriented analysis and design that will come as a great shock to many designers if they leave out consideration of it. It has to do with the notion of a transaction Database specialists consider this in great detail, but the designer needs to be very aware of the need for proper transaction management, either through the database’s built-in transaction handling or by other means We have the idea of systems as networks of objects cooperating to solve the prob

lems Unfortunately, as with all societies, there are frequent conflicts of interest

Two use cases executing at the same time may if they are not designed properly

interfere with each other Consider two use cases, one to deposit money into an

account and one to withdraw it. They might implement the following steps

Transaction 1:

11.1 Read the account balance 11.2 Add the deposit amount to the balance

Transaction 2

T1.3 Record the new account balance T21 Read the account balance

12.2 Deduct the withdrawal amount from the balance

12.3 Record the new account balance

Now all is fine, provided that the two transactions do not overlap and both transactions are complete. However, if the transactions overlap, then you might get a

sequence something like the following

11.1 Read the account balance 11 2 Add the deposit amount to the balance

12.1 Read the account balance T2 2 Deduct the withdrawal amount from the balance

T1 3 Record the new account balance

T2 3 Record the new account balance

Now if you look carefully, you will see that the recording of the account balance for the deposit has been overwritten. Thus the deposit has been lost It is perfectly possible to construct scenarios where any two use cases that operate simultaneously on the same data will result in erroneous actions by the system if they are not controlled. When designing use cases that update Informa, various strategies need to be followed.


The notion of a transaction is common in the database world. A transaction is the smallest meaningful and coherent operation on a database. The property of transactions that databases try to maintain is that they either succeed or have no effect. A transaction that only partially completes leaves the database in a damaged state For example, a transaction that transfers funds between two accounts that fails after withdrawing from one account before depositing in the other will effectively lose money or at least lose the record of money).

Few computer languages incorporate the notion of a transaction, and the implementation is usually subordinated to the database. However, the designer cannot ignore the notion of a transaction, or the system that is constructed will allow for actions that compromise the integrity of the system. Use cases are either single transactions or may be made up of a series of transactions. If the use case does not require the update of information, it is probably safe to ignore the issue of transactions. However, if the use case does update Informa- on, then the designer needs to prescribe how those updates take place.

The result of any two transactions on a system needs to be as if the two transactions 1462 SERIALIZABILITY happened in strict order, one after the other, even if the actual operation of the transactions overlap This is known in database circles as the serializability constraint If use cases are designed without consideration of this, then the system

is seriously compromised. The usual solution to this is some form of locking strategy. If a use case is going to update a prevent a record and use other information to determine the update, it needs to other use cases from doing the same until the update is complete. Thus, when information is retrieved from a database, it is often necessary to lock that information to prevent other use cases from using it. When another use case comes across a piece of locked information, it can either wait for the information to become unlocked, or it can quit. The use case holding the lock can proceed safely When the work is complete, the lock can be released. Any use case waiting on the lock can then proceed.

You can think of locks as traffic lights. Whenever the paths of two use cases meet, one needs to proceed safely before the other crosses its path, or it will crash. However, the user can hold several locks, so it can be holding up several use cases, which in turn might be holding up lots of other use cases. Locking is a simple idea, but it does lead to problems. The first one is deadlock.

Two or more use cases can sit waiting for each other to proceed. When this happens, one or more of them will have to back down, or parts of the system will be stuck forever. There are various strategies for dealing with this, which are mostly outside the scope of this book. One way is to have some sort of deadlock detection. Another (known as optimistic locking) is to leave all of the updates to the end of a transaction and make sure just before he writes that all the dependent data has not been updated by another use case; if another use case got there first, the use case rolls back.

Databases come with a variety of locking strategies. It is common to be able to lock individual records in tables, though some databases only implement table-level locking. Part of the design team’s duties involves understanding the locking strategies available and implementing them accordingly.


Transactions need to be atomic. That is, they are indivisible in their effect. Either they succeed completely, or they do not succeed at all. An account transfer transaction must be complete or have no effect. If the computer system fails Metalwho in the middle of the transaction, or the use case has to be aborted for some reason, then any updates that the transaction has made must be undone, and any locks that the transaction has obtained must be released.


The natural place for transaction handling is in the control object for a use case.