Hibernate不会驱逐查询缓存(不可重复读取问题) [英] Hibernate does not evict query cache (non repeatable read issue)

查看:149
本文介绍了Hibernate不会驱逐查询缓存(不可重复读取问题)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

现在我正在开发web应用程序。我是java / spring / hibernate的新成员,经过几年的.Net编程,真的感受到了java的热爱。 使用Spring(MVC,声明式事务)和Hibernate(3.6,作为缓存provier - ehCache 2.5)。我有一些只读和读写enitties,我想缓存使用Hibernate的第二缓存和查询缓存。



当我使用缓存读取时,一切都很好只有实体。我添加了读写实体并使用jMeter运行性能测试。对于读写实体,我面临着不可重复读取的问题。例如。有几个并发线程正在读写实体表。



线程3获取查找值:

  16:34:45,304 DEBUG [http-bio-8080-exec-3] cache.StandardQueryCache :( StandardQueryCache.java:136) - 缓存的查询结果不是最新的
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 =?

它发现缓存并不是最新的并加载实体,将它们添加到二级缓存中,实现并返回...从这里直到16:34:45,826的连续过程

同时线程9删除一个实体并更新二级缓存+时间戳:

  16:34:45,799 DEBUG [http-bio-8080-exec-9] hibernate.SQL:(SQLStatementLogger.java:111) -  delete来自virtual_device_class where virtual_device_class_id =? 
16:34:45,814 DEBUG [http-bio-8080-exec-9] cache.UpdateTimestampsCache:(UpdateTimestampsCache.java:95) - 空间失效[virtual_device_class],时间戳:5466792287494145


  16:34:45,826 DEBUG [http-bio-8080-exec-3] cache.StandardQueryCache :( StandardQueryCache。 java:96) - 在区域中缓存查询结果:org.hibernate.cache.StandardQueryCache; timestamp = 5466792287543296 

因此,在此时删除的ID将会在查询缓存中并且查询缓存将会被认为是最新的。

  16:34:45,852 DEBUG [http-bio-8080-exec-9] cache.UpdateTimestampsCache :( UpdateTimestampsCache.java: 122) -  [virtual_device_class]上次更新时间戳:5466792287494145,结果集时间戳:5466792287543296 

再次查找它会查找查询缓存,然后开始从第二个缓存实现实体。

  16:34:45,852 DEBUG [http-bio-8080-exec-9] cache.StandardQueryCache :( StandardQueryCache.java: 140) - 返回缓存的查询结果

但删除的项目不会在那里,所以查询数据库将做完了。

  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) - 选择virtualdev0_.virtual_device_class_id为virtual1_45_0_,virtualdev0_.virtual_device_class为virtual2_45_0_,virtualdev0_.sitebox_id为sitebox3_45_0_,virtualdev0

由于我使用Load方法,因此如果在db中找不到实体,它将抛出异常。
在我的个案实体中很少会更新,它可能会发生,这让我很担心。我有几个想法如何尝试克服这个问题:
$ b $ a)在数据库中设置trx隔离级别为可重复读取(但不要认为它会有所帮助,因为添加到缓存逻辑发生在从数据库中读取数据后
b)手动强制标准查询缓存驱逐实体删除/更新
c)根本不使用查询缓存(尝试将大部分数据库查询路由到使用第二个缓存)



以前有没有人遇到过这个问题?

解决方案

<



这个问题可能与方法 SessionFactory中的同步块被删除有关。 getQueryCache(String regionName) $ b

链接到休眠问题


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

这篇关于Hibernate不会驱逐查询缓存(不可重复读取问题)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆