hi folks, I am a new to java world so sorry for stupid questions but really appreciate if you can advise
I am working on web app using Spring (3.1: 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 kind of non repeatable read issue for my entity called as read-write. E.g. there are several concurrent threads reading and writing to entity table.
Thread 3 gets lookup values:
Code:
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:
Code:
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):
Code:
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.
Code:
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.
Code:
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.
Code:
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) try to use transactional concurrency strategy with JBoss cahche or ehCache
d) 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?