Reputation: 1238
I have some troubles understanding the OPTIMISTIC LockMode.
Let's consider in the following scenario: "Thread A creates a Transaction and reads a list of all Users from Table USERS. Thread B updates a user in Table USERS. Thread B commits. Thread A commits".
Assume I am using OPTIMISTIC Locking. Would in this case the 2nd commit cause the OptimisticLockException to be thrown ?
Because according to this docu: "During commit (and flush), ObjectDB checks every database object that has to be updated or deleted, and compares the version number of that object in the database to the version number of the in-memory object being updated. The transaction fails and an OptimisticLockException is thrown if the version numbers do not match".
No Exception should be thrown because the version number is checked only for those entities, which has to be updated or deleted.
BUT
This docu is saying: "JPA Optimistic locking allows anyone to read and update an entity, however a version check is made upon commit and an exception is thrown if the version was updated in the database since the entity was read. "
According to this desc the Exception should be thrown, because the version check is made upon commit (I assume they mean every commit including the commits after read).
I want to achieve that the described scenario should not throw any Concurency Exception, it's no problem if Thread A returns a list of users, which is not the most recent. So is it correct to use optimistic Locking or if not which LockType should I use ?
Upvotes: 0
Views: 2596
Reputation: 8332
Optimistic locking is very simple to understand:
Each entity have a timestamp / version numer attribute.
Each time an entity is updated, the timestamp / version number is updated too. When you update an entity, you first read the actual timestamp in persistence layer (the database) if it has changed since the time you loaded it, then an OptimisticLockException is thrown, otherwise it's updated along with the new timestamp / version number.
If you have no risk of concurrent update then you shouldn't use any lock mechanism cause even the optimistic one have a performance impact (you have to check the timestamp before updating the entity).
Pessimistic locking is a scalability issue because it allow only one access for update at a time on a given resources (and so other -not read only- accesses are blocked), but it avoid operations to fail. If you can't afford to loose an operation go with pessimistic if scalability is not an issue, otherwise handle the concurrency mitigation at business level.
Upvotes: 1
Reputation: 566
The two links you gave say the same thing. If an entity is being updated in TransactionA and it has been modified in the DB by TransactionB since TransactionA read the entity, then an OptimisticLockException will be thrown.
In your case you are retrieving a list of all Users in threadA, but you update only one. You will get the OptimisticLockException only if the same entity was changed and committed(attempted) in threadb.
You would want an exception to be thrown in this case otherwise only one of the updates will succeed – the last one to commit would simply override the earlier commit - but which one will be the last one is somewhat indeterminate – sometimes threadA sometimes threadB and the DB contents will be really not as intended. So locking prevents this undesired behaviour.
If your application transactions are regularly colliding with data consider using pessimistic locking also described in https://blogs.oracle.com/carolmcdonald/entry/jpa_2_0_concurrency_and
Upvotes: 2