首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Hibernate不驱逐查询缓存(不可重复读取问题)

Hibernate不驱逐查询缓存(不可重复读取问题)
EN

Stack Overflow用户
提问于 2012-04-18 15:30:49
回答 1查看 1.7K关注 0票数 3

我是一个java/spring/hibernate的新手,在经历了几年的.Net编程后,我真的爱上了java。

现在我正在使用Spring (MVC,声明性事务)和Hibernate (3.6,作为缓存提供者- ehCache 2.5)来开发web应用程序。我想使用Hibernate二级缓存和查询缓存来缓存一些只读和读写元素。

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

线程3获取查找值:

代码语言:javascript
复制
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=?

它发现缓存不是最新的,并加载实体,将它们添加到二级缓存,物化并返回…从此处到16:34:45,826的连续过程

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

代码语言:javascript
复制
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

线程3继续内部管理活动,最后将查询结果添加到查询缓存中(请注意,线程9的删除操作的时间戳将高于时间戳):

代码语言:javascript
复制
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

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

代码语言:javascript
复制
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

因此,当您再次尝试查找时,它将在查询缓存中查找,然后开始物化第二个缓存中的实体。

代码语言:javascript
复制
16:34:45,852 DEBUG [http-bio-8080-exec-9] cache.StandardQueryCache:(StandardQueryCache.java:140) - returning cached query results

但删除的项目将不在那里,因此将完成对数据库的查询。

代码语言:javascript
复制
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

因为我使用的是Load方法,所以如果在db中找不到实体,它会抛出异常。在我的情况下,实体很少更新,这可能会发生,这让我很担心。我对如何克服这个问题有几个想法:

a)在数据库中将trx隔离级别设置为可重复读取(但不要认为这会有所帮助,因为添加到缓存逻辑是在从数据库读取数据之后发生的) b)手动强制标准查询缓存在实体删除/更新时驱逐c)根本不使用查询缓存(尝试路由大多数数据库查询以使用第二个缓存)

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

EN

回答 1

Stack Overflow用户

发布于 2012-04-24 20:52:52

我已经迁移到Hibernate 4,它现在工作得很好。

此问题可能与在方法SessionFactory.getQueryCache(String regionName)中删除同步块有关

link to hibernate issue

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10204876

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档