0
votes

as pessimistic lock can only apply on a single database transaction. and keep the database transaction open during user think time, with locks held in the database is thought as anti-pattern, then what is the correct way to implement pessimistic lock with user think time in between?

I know how to implement optimistic locking in long conversation with user think time in between, just don't know how to implement pessimistic locking in long conversation with user think time in between.

1

1 Answers

1
votes

The short answer is that there is no "simple recipe" for doing this, nor any ready solution from Hibernate or any other ORM framework.

The long answer:

You'll have to figure out how to implement some features that will allow your application to emulate the database lock behavior for your "long conversation".

The most important thing is to make sure once a user starts using a piece of information (database row, or a set of objects, whatever fits your case), that information will not be used/manipulated by any other user. Also you'll have to make sure you have some policy on releasing the information, either when the user completes an operation, or after a certain amount of time has passed (you don't want an eternal lock on your information).

Since I don't know the details about your app, I will give an abstract example that may serve as an inspiration for your case. Certainly it's not the only solution.

Please, have in mind that every step will be contained in a single transaction because, in the end, your long conversation will be a series of requests in your web app.

Also, assuming the info from the question tags, this answer is aiming for a solution in a simple web app that connects to a DB. No "fancy exotic" architecture.

In a given table that needs such control, add 2 columns: one will be a user ID, the other a timestamp. This will control who has a "lock" on a row, and the time it was acquired.

When a user starts using the data contained in the table's row, your app will update the row with the user ID and current date/time. This is the most important step, because you'll have to deal correctly with concurrency. If more than one user tries to acquire a "lock" on the row, your app has to concede the lock for only one user. This step will most likely need to use a database lock in a single transaction. Make sure this step is fast and not attached to other operations, so the the database lock won't have a big impact in your app.

After the user has finished manipulating the data, the app can simply turn the user ID and timestamp to null, and after that, other user will be able to use it.

If the user for some reason did not finish the task, you'll have to apply some kind of "release" policy. In simple cases a simple time expiration will solve this problem. If a given user tries do acquire "lock" on a row that already has a lock, your app will check the timestamp. If the timestamp is expired, the new user overrides the lock. If not, the row is not available.

There are other more complex scenarios. If during your process the information is changed in the database before the operation is fully completed (let's say the user makes various information changes, and they are sent to the DB, before the user finishes the operation and "releases" the row), maybe you'll have to figure out how to implement a rollback. Maybe it's OK to leave the data "half manipulated", maybe not, it depends on your business needs.

Making this long story short:

  • the lock is made of columns in your database table
  • your code controls the lock

  • user tries to acquire lock

  • if row is free, or previous lock is expired, lock is acquired
  • after operation is done, lock is erased

Think carefully if any of this advice is applicable to your scenario.

I hope this was helpful.