Pessimistic Lock Timeouts setting

#1

Hi,

  I realise that JPA2 doesn't necessarily define a standard API way for Lock Timeouts. However, there is a standardised query 'hint' that can be setup to make the underlying DB lock a record for a specific time. The hint property is: "javax.persistence.lock.timeout"

I have a situation where multiple threads can hit a shared counter (which is used to track separate customers product index) - and my test case is failing here. The issue is that once the pessimistic lock is in place on the record, a subsequent access (which is a valid scenario for me) would instantly throw a:

com.objectdb.o._LockTimeoutException: Write lock cannot be granted for a.b.c.d.EE#150. irrespective if I set it at '0' all the way to '10000' (10 seconds) I can't accomplish this. The ideal case would be that the current application method 'sleep' until the lock is released. Is this possible? I realise setting a shared lock in the EJB could get around this, but this would be global and impact all threads.

 

My situation is where many clients from 1 company are accessing the same counter when bulk uploading products.

 

#2

This should be a useful feature.

I will check if it could be added in one of the next builds.

ObjectDB Support
#3

That would be fantastic! I realise that JPA2 however is lacking in this area (hence why they made it a 'hint' - that should be considered non-portable).

Thanks again for the prompt answers. In the meantime, I'll use an optimistic lock and fail on stale updates.

#4

Support of pessimistic lock timeout setting (javax.persistence.lock.timeout) was just added in build 2.2.3_02.

Please check the documentation and try it.

ObjectDB Support
#5

Thanks for the prompt implementation.

Although I see that the threads in contention are being blocked, subsequent threads are still getting errors (after the pause). Using TestNG, my settings are

* threadPoolSize=10

* invocationCount=50

(that is a pretty aggressive test)

Exception is:

Failed to update object com.x.y.z.ProductCodeTracking:1 - locked by another owner (error 672)

And finally,

Caused by: com.objectdb.o._LockTimeoutException: Write lock cannot be granted for com.x.y.z.ProductCodeTracking:1

I have to stress, that the pessimistically locked entity has a transaction propagation of REQUIRES_NEW. But it also fails if part of the original transaction (which has REQUIRED).

I haven't got an easily distributable test for replication, but It shouldn't take too long to write one up if required.

 

Thanks again.

#6

The new lock timeout support is covered by unit tests, but if you can provide additional tests, particularly if they demonstrate problems - it will help.

Notice, however, that the new change doesn't eliminate these exceptions - when the timeout is exceeded the exception is thrown. Can you get the exception even if you use a very high timeout value?

ObjectDB Support
#7

My apologies, I haven't updated this thread. I have not got the issue again and I consider this to be done and dusted. 

 

Thanks!

#8

OK. Thank you for the update.

ObjectDB Support
#9

Hi.

I am using Objectdb version 2.3.7_01. I am developing a test program which processes the stock data of an exchange market. The program creates one processor bean with an injected stateful EJB which holds an instance of Entity Manager for each stock. This bean holds the currents state of a stock and creates a short life FutureTask for each new update of stock. The FutureTask is executed by a ThreadPoolExecuter and the result is stored in ObjectDB. Due to huge number of stock and updates, I need to use many threads to process this data which may be more that 10 threads at a time. The System works, however, sometimes it throws this exception:

Failed to update object com.x.y.z.Stock:1 - locked by another owner (error 672)

I used pessimistic lock to lock the stock objects. Since the adaptor which resides between exchange market and my program, only relays some specific updates to the processor bean (such as price data). The rest of updates are written in ObjectDB by the adaptor itself. In order to avoid any clash between the updater threads of the processor bean and adaptor, pessimistic lock is used.

Is this exception due to the limited number of supported thread by ObjectDB?

(The default number of supported threads in ObjectDB configuration file is 10)

Your prompt reply will be appreciated.

Thank you and regards.

#10

The error message indicates an attempt to update an object that is still locked (with pessimistic lock) by another transaction (usually in another thread).

Notice that pessimistic locks are automatically released when the transaction is ended, but transactions that began before the releasing transaction is ended may still see objects as locked.

Naturally lock failures are more common when using more threads.

ObjectDB Support
#11

What did you set your timeout settings for the javax.persistence.lock.timeout to?

 

I used  5 seconds (5000 milliseconds) and I never saw the issue again. I assume you are using pessimistic locking due to a highly concurrent system that requires integrity on some value. Rest assured, my prototype app (Stale as of july last year due to work commitments) has never seen the issue again. Support for objectDB is faster than I've seen on any commercial app.

 

To set the timeout settings, just follow the JPA2 spec - so you can do it per query, or global using persistence.xml.

 

Cheers

 

#12

Hi.

You are right Willks. ObjectDB support is fantastic. There was nothing wrong with my timeout settings. My timeout is 4000 in persistence.xml. There was no timeout exception in my program.

I would like to thank ObjectDB support for giving me the hint:

"Notice that pessimistic locks are automatically released when the transaction is ended, but transactions that began before the releasing transaction is ended may still see objects as locked."

 I had made a mistake in the design of my processor bean. This bean is a simple bean and does not support transaction. I used to retrieve my stock object by a JPA EJB. However, after retrieval, once the control was returned to proccessor bean from the JPA EJB method call, the transaction also ended. As a result, the processor bean was processing the unlocked stock object. Any other thread which could lock the stock object after this stage, would not allow the processor bean to  apply the updates.

I converted my processor bean to a stateless EJB and the problem was solved. I could not reply you until Monday morning. since the exchange market is closed during weekend and no stock data feed is available. I had to wait until it opens and I can test my program.

Once again, I appreciate objectdb support and you for immediate replies.

Regards.

Reply