我是java/spring/hibernate中的新成员,经过几年的.Net编程后,在java中真正感受到了爱。Hibernate不会驱逐查询缓存(不可重复读取问题)
现在我正在使用Spring(MVC,声明性事务)和Hibernate(3.6,作为缓存provier-ehCache 2.5)的web应用程序。我有一些只读和读写enitties,我想用Hibernate缓存和查询缓存来缓存。
当我为只读实体使用缓存时,一切正常。我添加了读写实体并使用jMeter运行性能测试。对于读写实体,我面临着不可重复读取的问题。例如。有几个并发线程正在读写实体表。
线3的查找值:
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:45826
同时螺纹9删除实体之一,并更新二级缓存+时间戳:
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继续看家活动最后增加了查询结果的查询缓存(请注意,时间戳会比timpestamp螺纹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
因此,在这个时间点删除ID将在查询缓存和查询缓存将被认为是最新的。
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
所以,当你试图让查找再次它将在查询缓存,然后将开始从第二高速缓存物化实体。
16:34:45,852 DEBUG [http-bio-8080-exec-9] cache.StandardQueryCache:(StandardQueryCache.java:140) - returning cached query results
但删除的项目不会在那里,所以查询分贝将完成。
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方法,因此抛出异常,如果实体没有在数据库中找到。 在我的情况下,实体很少更新它可能发生,这令我担心。我有几个想法如何尝试克服这个问题:
a)将trx隔离级别设置为DB中的可重复读取(但不要认为这会有所帮助,因为在从db读取数据之后添加到缓存逻辑) b)手动强制标准查询缓存驱逐在实体删除/更新 C)根本不使用查询缓存(尝试路由大多数数据库查询使用第二缓存)
有没有人面对这个问题之前, ?