我是新来的Java /春/休眠和真正感受到爱情在Java经过几年的.NET编程的。
现在我正在使用Spring(MVC,声明式事务)和Hibernate的Web应用程序(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) - 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方法,所以如果实体不在分贝发现它抛出异常。 在我的情况下,实体将很少更新,可能会发生,并且令人担忧的我。 我有一些想法如何设法解决这个问题:
一)设置TRX隔离级别设置为可重复读的DB(但不认为它会帮助,因为增加了高速缓存逻辑读取从数据库数据后发生),B)手动强制标准查询缓存驱逐在实体删除/更新三)做在所有未使用查询缓存(尝试路由大多数数据库查询使用第二缓存)
有没有人面对之前这个问题?