Gilgamesz
Gilgamesz

Reputation: 5063

Optimistic locking and scalibility

I wonder what is the purpose of optimistic locking mechanism in Hibernate. So, I've read here

https://vladmihalcea.com/preventing-lost-updates-in-long-conversations/ about such scenario:

1. Alice requests a certain product for being displayed
2. The product is fetched from the database and returned to the browser
3. Alice requests a product modification
4. The product must be updated and saved to the database

And, indeed it seems to be reasonable to use optimistic locking in such scenarios.

But, managed or detached entities are tracked / kept in Persistence Context. Persistence Context is limited to memory process. Does it mean that it can be used when there is at most one instance of service?

Upvotes: 2

Views: 1455

Answers (1)

Nathan
Nathan

Reputation: 1661

The basic assumption of optimistic locking is that you will not be editing the same record in parallel. That means that we do not not perform any explicit locking or synchronizing. We load data and then perform a write operation. If another transaction has written to the same record, then the write operation will fail. However, it is independent from the number of service instances. In fact, it is possible for an application to function well using optimistic locking and an arbitrary number of service instances.

Consider the following example. Once you have an entity where you have a property annotated with @Version as follows...

@Entity
@Table(name="test_entity")
    public class TestEntity implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id", nullable = false, unique = true)
    private Long id;
    @Column(name = "value", nullable = true)
    private String value;
    @Version
    @Column(nullable = false)
    private Integer version;

    ... getters & setters

}

Then the code:

session.saveOrUpdate(testEntity);
session.flush();

will generate the following query...

update
    test_entity 
set
    value=?,
    version=? 
where
    id=? 
    and version=?

If the version has been changed through a parallel transaction either in the same service instance or a separate instance, then hibernate will note that the update did not affect any rows in the database because the ID matched, but the version had been changed via a different transaction.

Any time this is the case (that the session.update(...) method affects 0 rows), hibernate will throw a runtime exception to indicate that an optimistic lock has failed - OptimisticLockException. That means the primary consideration is whether or not you believe that your users will be simultaneously updating the same record.

However, if you are using a second level cache and you want to combine it with optimistic locking, then you will need to make sure that you are using a correctly configured distributed cache. Otherwise the second-level-cache means that you will load the instance from the second-level-cache (not from the persistance context) instead of from the database. In the absense of a distributed cache, your second-level-cache of course, would have no idea that a different service instance updated the record, resulting in a version increment. Then when you go to update the record in the database (using the query above) you update 0 records and get an OptimisticLockException.

Upvotes: 3

Related Questions