Optimistic versus Pessimistic Locking

Pessimistic Locking

Locking is a mechanism that prevents concurrent access to a particular item of data. When one transaction holds a lock on an item, no concurrent transaction can read and/or modify this item. A lock might be just a momentary lock, held while the item is being read, or it might be held until the completion of the transaction. A pessimistic lock is a lock that is acquired when an item of data is read and that is held until transaction completion.

In read-committed mode (our preferred transaction isolation level), the database never acquires pessimistic locks unless explicitly requested by the application. Usually, pessimistic locks aren’t the most scalable approach to concurrency. However, in certain special circumstances, they may be used to prevent database-level deadlocks,
which result in transaction failure. Some databases (Oracle and PostgreSQL, for example) provide the SQL SELECT…FOR UPDATE syntax to allow the use of explicit pessimistic locks.

Optimistic Locking

Optimistic Locking is implemented using “managed versioning” in Hibernate.

In our CaveatEmptor application, both the user who posted a comment and any system administrator can open an Edit Comment screen to delete or edit the text of a comment. Suppose two different administrators open the edit screen to view the same comment simultaneously. Both edit the comment text and submit their changes. At this point, we have three ways to handle the concurrent attempts to write to the database:

■ Last commit wins—Both updates succeed, and the second update overwrites
the changes of the first. No error message is shown.
■ First commit wins—The first modification is persisted, and the user submitting
the second change receives an error message. The user must restart the
business process by retrieving the updated comment. This option is often
called optimistic locking.
■ Merge conflicting updates—The first modification is persisted, and the second
modification may be applied selectively by the user.

Managed versioning relies on either a version number that is incremented or a timestamp that is updated to the current time, every time an object is modified. For Hibernate managed versioning, we must add a new property to our Comment class  and map it as a version number using the <version> tag.

Whenever Hibernate updates a comment, it uses the version column in the SQL WHERE clause:
update COMMENTS set COMMENT_TEXT=’New comment text’, VERSION=3
where COMMENT_ID=123 and VERSION=2

If another application transaction would have updated the same item since it was read by the current application transaction, the VERSION column would not contain the value 2, and the row would not be updated. Hibernate would check the row count returned by the JDBC driver—which in this case would be the number of rows updated, zero—and throw a StaleObjectStateException.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: