Optimistic Locking
Optimistic Locking
“Labelling this scheme optimistic maligns a perfectly good philosophy.”
(“Transaction Processing: Concepts and Techniques”, p435, Gray & Reuter, 1993, ISBN 1-55860-190-2).
In an effort to increase concurrency, some database management systems offer optimistic locking, in which locks in a read-write transaction are released early, and the transaction proceeds on the assumption that data objects will not be changed before commit. This assumption is checked at commit, causing the transaction to be rolled back if it is found that an object has indeed been changed by another transaction in the meantime.
Optimistic locking can improve concurrency in applications where the majority of transactions are read-only, since these are able to proceed when they might otherwise be blocked by an exclusive lock of a read-write transaction. However, if too many transactions are read-write then it causes all but one of the contending transactions to abort commit and rollback, to be re-tried from the beginning, which, as the above quotation suggests, may be worse than just waiting for locked objects to become available.
Optimistic locking is a special case of a more general technique known as a “field-call”, in which the assumption checked on commit is a more general predicate than just “not changed by another transaction”. For example, the condition tested could be the that the quantity-on-hand of an inventory item is still greater than zero at commit, even if it has been changed in the meantime, together with a deferred update in a redo log entry which is applied if the condition stored there is found still to be true. Unlike simple optimistic locking, field-calls do improve concurrency of contending read-write transactions, but the disadvantage is that such transactions do not see their own updates if they make more than one change to the same object.
Application-specific optimistic locking
Neither optimistic locking nor field calls are implemented in VOSS 3.1. However, application-specific optimistic locking can be programmed for specified objects by designing the application to make working copies (VORefPublic>>realCopy) and note their last commit timestamp (VORefPublic>>timestamp), during a preliminary read-only transaction which then rolls back, releasing its locks.
These real (i.e. non-virtual) working copies may be changed at leisure in a read-write transaction, and then used to update their respective virtual (persistent) originals (VORefPublic>>voPoke:), after having checked that none of them (this is an all or nothing transaction) has a timestamp (VORefPublic>>timestamp) later than it had when the working copy was made, which would indicate a change having been committed by another transaction in the meantime, thus invalidating the basis for commit.
Before poking in the changed working copy, be sure that that copy is never going to be sent another message, as it is that actual granule which is to be poked into the virtual object, and direct messages to it are then subversive and illegal. In practice this may be assured by using temporary variables to reference the working copies. If for some reason this cannot be assured, then update the virtual object by poking in a copy of the modified working copy. As the working copy is an arbitrary structure of Smalltalk objects, this copy of it should be made using the message: Object>>voTotalCopy.
Will optimistic locking help or hinder? When choosing between automatic pessimistic locking and programmed optimistic locking, consider the statistics of the application. How often will other transactions need objects whilst they are being updated? Does it matter if their transaction has to wait for an updating user to finish?
Consider imposing a time limit on potentially long open-ended read-write transactions, which a user might begin and accidentally leave open, holding locks, whilst attending to some other task such as lunch.
If the majority of transactions are updates, programmed optimistic locking will probably not give better results than the automatic pessimistic locking, as it means that lock waits are converted into aborted commits, which require the transaction to be restarted from the beginning.
