Hibernate does not evict query cache (non repeatable read issue) - java

I am a new to java/spring/hibernate and really felt in love in java after several years of .Net programming.
now I am working on web app using Spring (MVC, declarative transactions) and Hibernate (3.6, as cache provier - ehCache 2.5). I've got some read only and read-write enitties that I would like to cache using Hibernate second cache and query cache.
everything was alright when I used caching for read only entities. I added read-write entity and ran performance tests using jMeter. For read-write entities I am facing with the issue of non repeatable read. E.g. there are several concurrent threads reading and writing to entity table.
Thread 3 gets lookup values:
16:34:45,304 DEBUG [http-bio-8080-exec-3] cache.StandardQueryCache: (StandardQueryCache.java:136) - cached query results were not up to date
16:34:45,304 DEBUG [http-bio-8080-exec-3] hibernate.SQL:(SQLStatementLogger.java:111) - select virtualdev0_.virtual_device_class_id as virtual1_45_, virtualdev0_.virtual_device_class as virtual2_45_, virtualdev0_.sitebox_id as sitebox3_45_, virtualdev0_.timestamp as timestamp45_ from virtual_device_class virtualdev0_ where virtualdev0_.sitebox_id=?
It finds out that cache is not up to date and loads entities, adds them to second level cache, materializes and returns… continuous process from here and up to 16:34:45,826
Meanwhile Thread 9 deletes one of entities and updates second level cache + timestamp:
16:34:45,799 DEBUG [http-bio-8080-exec-9] hibernate.SQL:(SQLStatementLogger.java:111) - delete from virtual_device_class where virtual_device_class_id=?
16:34:45,814 DEBUG [http-bio-8080-exec-9] cache.UpdateTimestampsCache:(UpdateTimestampsCache.java:95) - Invalidating space [virtual_device_class], timestamp: 5466792287494145
Thread 3 continues house keeping activities and finally adds query result to query cache (notice that timestamp will be higher than timpestamp for delete action of Thread 9):
16:34:45,826 DEBUG [http-bio-8080-exec-3] cache.StandardQueryCache:(StandardQueryCache.java:96) - caching query results in region: org.hibernate.cache.StandardQueryCache; timestamp=5466792287543296
Thus at this point of time deleted ID will be in query cache and query cache will be considered as being up to date.
16:34:45,852 DEBUG [http-bio-8080-exec-9] cache.UpdateTimestampsCache:(UpdateTimestampsCache.java:122) - [virtual_device_class] last update timestamp: 5466792287494145, result set timestamp: 5466792287543296
So when you try to get lookups again it will look in query cache and then will start materializing entities from the second cache.
16:34:45,852 DEBUG [http-bio-8080-exec-9] cache.StandardQueryCache:(StandardQueryCache.java:140) - returning cached query results
But deleted item won't be there, so query to db will be done.
16:34:45,863 DEBUG [http-bio-8080-exec-9] loader.Loader:(Loader.java:2022) - loading entity: [com.test.models.VirtualDeviceClass#0b2f363f-fbb9-4d17-8f86-af86ebb5100c]
16:34:45,873 DEBUG [http-bio-8080-exec-9] hibernate.SQL:(SQLStatementLogger.java:111) - select virtualdev0_.virtual_device_class_id as virtual1_45_0_, virtualdev0_.virtual_device_class as virtual2_45_0_, virtualdev0_.sitebox_id as sitebox3_45_0_, virtualdev0
As I am using Load method so it throws exception if entity is not found in db.
in my case entities would be rarely updated it might happen and that's worrying me. I've got few ideas how to try to overcome this issue:
a) set trx isolation level to Repeatable Read in DB (however do not think that it will help because adding to cache logic takes place after reading data from db)
b) manually force Standard Query Cache to evict on entity delete/update
c) do not use query cache at all (try to route most of db queries to use second cache)
Did anybody face with this issue before?

I have migrated to Hibernate 4 and it works fine now.
This issue might have been related to synchronized block being removed in method SessionFactory.getQueryCache(String regionName)
link to hibernate issue

Related

Session.flush() causes org.hibernate.StaleStateException: Batch update returned unexpected row count from update: 1 actual row count: 0 expected: 1

I have a java back-end web application that just started throwing an error after some sort of database update.
I've been able to isolate the code to a single line in which a Session variable is being flushed:
Session session=getSession();
session.saveOrUpdate(parm);
session.flush(); //This is where it errors
And it throws this error:
ERROR AbstractFlushingEventListener Could not synchronize database state with session
org.hibernate.StaleStateException: Batch update returned unexpected row count from update: 1 actual row count: 0 expected: 1
The code hasn't changed in over a year; it just started throwing this error.
Any suggestions?
Thanks
This error usually caused when the hibernate can't find all the rows it needs to update. Meaning that when you try to update some objects that were pulled from the DB they don't really exist anymore (or never existed in the first place).
It might be because another thread is deleting them or that the DB's isolation mode is set to read_uncommited and so rows that were created by another transaction failed to save (due to a transaction failure) and don't exist anymore.
ref: https://stackoverflow.com/questions/21625059/org-hibernate-stalestateexception-batch-update-returned-unexpected-row-count-fr

javax.ejb.EJBTransactionRolledbackException: Transaction rolled back

(I didn't find proper answer from the existing questions that's why I posted this)
I have an application which processes quite big number of data. I am getting the below errors / exceptions and the process gets terminated. But increasing the ram size resolving the issue. (but we can't do it for some restriction)
2019-02-11 14:02:59,662 ERROR [net.xxx.RuleHandler] (Thread-185232 (HornetQ-client-global-threads-1521150484)) failed to get rules from db: org.hibernate.HibernateException: Transaction was rolled back in a different thread!
at org.hibernate.engine.transaction.synchronization.internal.SynchronizationCallbackCoordinatorTrackingImpl.processAnyDelayedAfterCompletion(SynchronizationCallbackCoordinatorTrackingImpl.java:105) [hibernate-core-4.2.27.Final-redhat-1.jar:4.2.27.Final-redhat-1]
2019-02-11 14:02:59,693 ERROR [net.xxx.ejb.SearchReqMDB] (Thread-185232 (HornetQ-client-global-threads-1521150484)) Something failed while search indexing: net.xxx.xxx.JMPException: javax.ejb.EJBTransactionRolledbackException: Transaction rolled back
How to resolve this issue? Do I need to increase the timeout value for ejb call? and if yes then where I need to change it.
Using JBOSS 6 EAP , EJB & JPA

Record inserted but still not found

I was currently using java spring jdbctemplate to insert and select record. However, Now the system have go for production, some issue has happen. This system will prevent record duplicate by select the record by certain key to check is it already exist. However, I notice the 1st transaction after inserted into database, then the 2nd transaction come in, jdbc template select still show that record was not found? I notice this will happen if the 2 transaction was submitted within a milliseconds different...
The record time was
e.g.
1st Record insert - 15/6/17 12:22:39,986 - insert success
2nd record select - 15/6/17 12:22:44,680 - search record show not found?
Sample insert log
15/6/17 12:22:39,937 DEBUG [30:http-nio-8080-exec-2] (org.springframework.jdbc.core.JdbcTemplate:869) Executing prepared SQL update
15/6/17 12:22:39,938 DEBUG [30:http-nio-8080-exec-2] (org.springframework.jdbc.core.JdbcTemplate:616) Executing prepared SQL statement [INSERT INTO ...;]
15/6/17 12:22:39,950 DEBUG [30:http-nio-8080-exec-2] (org.springframework.jdbc.core.JdbcTemplate:879) SQL update affected 1 rows
15/6/17 12:22:39,951 DEBUG [30:http-nio-8080-exec-2] (org.springframework.jdbc.core.JdbcTemplate:869) Executing prepared SQL update
15/6/17 12:22:39,952 DEBUG [30:http-nio-8080-exec-2] (org.springframework.jdbc.core.JdbcTemplate:616) Executing prepared SQL statement [INSERT INTO ...;]
15/6/17 12:22:39,965 DEBUG [30:http-nio-8080-exec-2] (org.springframework.jdbc.core.JdbcTemplate:879) SQL update affected 1 row
15/6/17 12:22:39,970 DEBUG [30:http-nio-8080-exec-2] (org.springframework.jdbc.datasource.DataSourceUtils:327) Returning JDBC Connection to DataSource
Sample select log
15/6/17 12:22:44,680 DEBUG [29:http-nio-8080-exec-1] (org.springframework.jdbc.core.JdbcTemplate:682) Executing prepared SQL query
15/6/17 12:22:44,680 DEBUG [29:http-nio-8080-exec-1] (org.springframework.jdbc.core.JdbcTemplate:616) Executing prepared SQL statement [SELECT * FROM ...]
Please note that this system was set in 2 different server by using load balancing. They both point to the same database. The insert was completed on server 1 because it already return the connection to the jdbc connection pool. A new transaction come in the server 2, select but no record found?
I wonder why it still cannot found event after insert was finish? Is it because of the time delay?
This question had been resolved. It was due to the server time not consistent. Thanks
RealSkeptic

Spring Jdbc template Row mapper is not setting all values in Object

I am using spring jdbc template to retreive 400 records from oracle database.
After that i am using row mapper to convert rows to objects. Some of the values in object are not having any values. when i test same sql in pl/sql editor, i am able to see all rows and all columns for rows. When i debug application, i am getting below error. If i fetch less number of records(7) for same query, it is working fine.Row mapper is setting all values for object. Can you please help me on this.
java.sql.SQLException: statement handle not executed
2017-02-09 15:45:39 INFO XmlBeanDefinitionReader:317 - Loading XML bean definitions from class path resource [org/springframework/jdbc/support/sql-error-codes.xml]
2017-02-09 15:45:39 INFO SQLErrorCodesFactory:126 - SQLErrorCodes loaded: [DB2, Derby, H2, HSQL, Informix, MS-SQL, MySQL, Oracle, PostgreSQL, Sybase, Hana]
2017-02-09 15:45:39 WARN SQLErrorCodesFactory:227 - Error while extracting database product name - falling back to empty error codes
org.springframework.jdbc.support.MetaDataAccessException: Error while extracting DatabaseMetaData; nested exception is java.sql.SQLException: Connection has already been closed.
at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:305)
at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:329)
at org.springframework.jdbc.support.SQLErrorCodesFactory.getErrorCodes(SQLErrorCodesFactory.java:214)
at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.setDataSource(SQLErrorCodeSQLExceptionTranslator.java:134)
at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.<init>(SQLErrorCodeSQLExceptionTranslator.java:97)
at org.springframework.jdbc.support.JdbcAccessor.getExceptionTranslator(JdbcAccessor.java:99)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:645)
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:680)
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:707)
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:757)
at org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.query(NamedParameterJdbcTemplate.java:192)
If retrieving those 400 rows from the database take some time, I assume you are hitting DB connection timeout. If so, increase connectionTimeout if you are using resource pool. Timeout could happen while you are debugging the code, too.
Could also be that timeout is on the database side. In that case, you'll have to tweak DB timeout parameters.

Thread associated with transaction suspended for a long time in JBoss 6.1.0

I am facing a big concern in JBoss 6.1.0. It is a multi threaded application and am using stateless EJB with BMT and Sybase DB. JDK used is 1.7.76u. User transaction is started. Queries got ran but the associated thread tries to commit after ONE HOUR. I am not aware what happened to the thread executing. It is suspended for sure but not from the code.
Can anyone please give a valuable pointer about why the thread got suspended for more than hour. Obviously after an hour, thread resuming and trying either COMMIT or ROLLBACK will fail and has failed as the default transaction timeout is 300 seconds (which is JBoss 6 default value).
2017-01-09 10:01:49,389 DEBUG [TestDAO] [EventId: ] [pool-63-thread-6] SQL SELECT QUERY
2017-01-09 10:01:49,391 DEBUG [TestDAO] [EventId: ] [pool-63-thread-6] ['dao.rowsProcessed']: 1 rows processed
2017-01-09 10:01:49,389 DEBUG [TestDAO] [EventId: ] [pool-63-thread-6] SQL UPDATE QUERY
2017-01-09 10:01:49,391 DEBUG [TestDAO] [EventId: ] [pool-63-thread-6] ['dao.rowsUpdated']: 1 row updated
2017-01-09 11:05:48,213 DEBUG [DAOUtils] [EventId: ] [pool-63-thread-6] commitTx
2017-01-09 11:05:48,214 ERROR [DAOUtils] [EventId: ] [pool-63-thread-6] commitTx() ARJUNA-16063 The transaction is not active!
2017-01-09 11:05:48,215 DEBUG [DAOUtils] [EventId: ] [pool-63-thread-6] rollbackTx
2017-01-09 11:05:48,215 ERROR [DAOUtils] [EventId: ] [pool-63-thread-6] rollbackTx() java.lang.IllegalStateException - BaseTransaction.rollback - ARJUNA-16074 no transaction!
It seems you have long running transactions which is being time-out.
"The transaction is not active!" are caused by a transaction timeout. When a transaction times out the transaction manager rolls it back asynchronously and then when a compontent tries to access the transaction again (e.g. to commit it or roll it back) it won't be able to according to the JTA spec.
The default transaction timeout has been defined under "default-timeout" attribute at "transactions" subsystem in the application server configuration.
The default is 300 seconds / 5 minutes.
You may modify the value to increase the default transaction timeout.
You may set the value to 0 to disable the transaction reaper/ transaction timeout.
The application server VM must be restarted for the default-timeout change to be applied.
<subsystem xmlns="urn:jboss:domain:transactions:1.4">
<coordinator-environment default-timeout="300"/> <!-- HERE -->
</subsystem>
It looks to me like your it is taking longer than 5 minutes to process the message therefore its transaction is timing out.
I would recommend you to increase the transaction timeout to a higher figure to avoid this situation. It would be good if you could refactor the application code to reduce the time taken to complete a transaction. So it may be that the application logic is correctly handling the scenario in this case
As I mentioned in the JBoss forum, this is not issue with the transaction timeout.
There is no point in extending the timeout for transaction as this blocks all the other applications because locks in the database is held by transaction.
Threads executing the transaction are frozen. Any hints on why this thread is blocked from committing would be of great help.
Rgds
Manohar

Categories