Hibernate Books

All times are UTC - 5 hours [ DST ]



Post new topic Reply to topic  [ 5 posts ] 
Author Message
 Post subject: Hibernate StaleStateException in concurrent transactions
PostPosted: Fri May 12, 2017 8:54 am 
Newbie

Joined: Wed Oct 19, 2016 2:57 am
Posts: 11
Hi all,
I've modified a method in a transaction adding a block that stores two entities.
One entity is annotated as:
Code:
@Entity
@Table(name = "loyalty_program")
@SelectBeforeUpdate(value = true)
@DynamicUpdate(value = true)
@OptimisticLocking


and with
Code:
@Version
   @Column(name = "version_lock", nullable = false)
   private Integer versionLock;


Needed to create a unique and sequential loyaltySerialNumber. In this block of code, only this serial is stored and another entity anotated as:
Code:
Entity
@Table(name = "loyalty_user")


There are a 1% of the transactions that throw this exception:

exception-0-Message:StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
exception-0-StackTrace:org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
at org.hibernate.jdbc.Expectations$BasicExpectation.checkBatched(Expectations.java:67)
at org.hibernate.jdbc.Expectations$BasicExpectation.verifyOutcome(Expectations.java:54)
at org.hibernate.engine.jdbc.batch.internal.BatchingBatch.checkRowCounts(BatchingBatch.java:138)
at org.hibernate.engine.jdbc.batch.internal.BatchingBatch.performExecution(BatchingBatch.java:115)
at org.hibernate.engine.jdbc.batch.internal.BatchingBatch.doExecuteBatch(BatchingBatch.java:97)
at org.hibernate.engine.jdbc.batch.internal.AbstractBatchImpl.execute(AbstractBatchImpl.java:147)
at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.executeBatch(JdbcCoordinatorImpl.java:220)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:611)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:456)
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:337)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1295)
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:468)
at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:3135)
at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2352)
at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:491)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:147)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$100(JdbcResourceLocalTransactionCoordinatorImpl.java:38)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:231)
at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:65)
at com.tiqueteo.backend.ServicesDispatcher.call(ServicesDispatcher.java:708)
at com.tiqueteo.backend.ServicesDispatcher.call(ServicesDispatcher.java:69)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)

Maybe is some problem with concurrency and befeore adding this block the transaction was not throwing any exception, all was working OK.
What's wrong with this entity LoyaltyProgram?


Top
 Profile  
 
 Post subject: Re: StaleStateException in concurrent transactions.
PostPosted: Fri May 12, 2017 10:53 am 
Hibernate Team
Hibernate Team

Joined: Thu Sep 11, 2014 2:50 am
Posts: 1177
If two transactions are modifying the same entity in the same time, this exception will be thrown. It's not something bad because it allows you to prevent lost updates.

If you disable optimistic locking, you will not get this exception, but you will get a lost update anomaly.

If you want to reduce the likelihood of conflicts, you can use the versionless optimistic locking mechanism.

_________________
If you liked my answer, you are going to love my High-Performance Java Persistence book and my blog as well.


Top
 Profile  
 
 Post subject: Re: Hibernate StaleStateException in concurrent transactions
PostPosted: Tue May 16, 2017 2:29 pm 
Newbie

Joined: Wed Oct 19, 2016 2:57 am
Posts: 11
Hi Vlad,
Thank you for your help.
I will try to catch this exception and retry the petition. We can do that and retry at most three times. If there's a lot of concurrency this will be a problem too, but can help.
The other option is move this logic of updating this table out of this transaction that has a lot of concurrency and do it in another transaction less concurrent if it's possible.
Anyway I thought that the exception thrown in this case should be LockAdquisitionException instead of StaleStateException.

Best regards.


Top
 Profile  
 
 Post subject: Re: Hibernate StaleStateException in concurrent transactions
PostPosted: Thu May 18, 2017 12:08 pm 
Newbie

Joined: Wed Oct 19, 2016 2:57 am
Posts: 11
By the way,
Is it possible that this kind of exceptions:
Code:
StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1

consume a lot of DB cpu in a rollback of "big" transactions (big in the sense of many entity stores)?.
We have some "big" transactions where some entities with optimisticLocking are updated, and if there's a lot of concurrency I guess this could be the cause of high cpu usage.

Best regards.


Top
 Profile  
 
 Post subject: Re: Hibernate StaleStateException in concurrent transactions
PostPosted: Thu May 18, 2017 2:55 pm 
Hibernate Team
Hibernate Team

Joined: Thu Sep 11, 2014 2:50 am
Posts: 1177
The rollback overhead in MVCC database engines is the reason why long-running transactions are to be avoided.

In this case, you should strive to keep the Persistence Context as slim as possible and split the work load into multiple steps that are executed in batches.

_________________
If you liked my answer, you are going to love my High-Performance Java Persistence book and my blog as well.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 5 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.