Optimistic Concurrency and Pessimistic Concurrency

Optimistic Concurrency:

This is a solution to lost updates caused by Read Committed in multi-threaded applications. The problem is here:

So, here the update made by transaction A is permanently lost because the last commit wins in read committed.

Optimistic concurrency is used to prevent these lost updates. In this mechanism, the first commit always wins. A @Version column is used in hibernate to ensure that no two transactions to the same record can not update at the same time.

Here update fails due to the version check

UPDATE table SET x = 15, vrsn = 4 WHERE id = 1 AND vrsn = 3

So, when a version conflict occurs Hibernate throws a StaleObjectStateException as follows:

In this bad lock situation, we can have the following solutions:

  1. we can then reload the data and apply their updates against the latest data (for example vrsn = 4).

  2. we can create a conflict merging page: allowing the user to merge differences made by two different transactions like git conflict merge.

NOTE: version conflict happens very rarely in optimistic concurrency. If concurrency is happening on the different records in the database then optimistic locking works well. So, optimistic locking is okay to use if conflict happens very rarely (solution: try once again message)

BUT

If too many users (transactions) are working on the same record in the database then pessimistic locking works well.

Pessimistic Concurrency:

Pessimistic locking might be required to prevent the unrepeatable reads problem. LockMode.UPGRADE possesses a read(shared lock) lock and write (exclusive lock)lock.

  1. Hibernate can request explicit database level locks to provide increased isolation.

  2. These locks will be released on commit

     Customer cust = (Customer)session.get(Customer.class, 1);
     session.lock(cust, LockMode.UPGRADE);