【问题标题】:Hibernate4, Grails 2.5 -- cached data persists between restarts?Hibernate4,Grails 2.5——缓存数据在重启之间仍然存在?
【发布时间】:2018-08-07 11:19:20
【问题描述】:

我在 Grails 2.5.0 应用程序中遇到了一个奇怪的 Hibernate4 缓存问题,该应用程序用作从遗留系统迁移的数据的平台。迁移涉及数据库记录的直接数据库插入和删除(在测试迁移 SQL 时)。这些操作导致系统中的页面加载错误,因为缓存的数据与数据库的实际状态不同。特定页面加载失败的堆栈跟踪错误表明缺少记录,其 ID 当前未被数据库中的任何内容通过外键引用。例如,一个页面无法呈现并出现以下错误:

018-02-27 10:16:32,495 http-bio-8080-exec-8 | ERROR  StackTrace | superAdmin | Full Stack Trace:                                                
org.hibernate.UnresolvableObjectException: No row with the given identifier exists: [com.tlc.worx.company.CompanyQuestion#48466]                 
        at org.hibernate.UnresolvableObjectException.throwIfNull(UnresolvableObjectException.java:68)                                            
        at org.hibernate.event.internal.DefaultRefreshEventListener.onRefresh(DefaultRefreshEventListener.java:179)                              
        at org.hibernate.event.internal.DefaultRefreshEventListener.onRefresh(DefaultRefreshEventListener.java:61)                               
        at org.hibernate.internal.SessionImpl.fireRefresh(SessionImpl.java:1121)                                                                 
        at org.hibernate.internal.SessionImpl.refresh(SessionImpl.java:1094)                                                                     
        at org.hibernate.internal.SessionImpl.refresh(SessionImpl.java:1089)                                                                     
        at org.codehaus.groovy.grails.orm.hibernate.GrailsHibernateTemplate$10.doInHibernate(GrailsHibernateTemplate.java:342)                   
        at org.codehaus.groovy.grails.orm.hibernate.GrailsHibernateTemplate.doExecute(GrailsHibernateTemplate.java:188)                          
        at org.codehaus.groovy.grails.orm.hibernate.GrailsHibernateTemplate.refresh(GrailsHibernateTemplate.java:339)                            
        at org.codehaus.groovy.grails.orm.hibernate.GrailsHibernateTemplate.refresh(GrailsHibernateTemplate.java:335)                            
        at org.codehaus.groovy.grails.orm.hibernate.HibernateGormInstanceApi.refresh(HibernateGormInstanceApi.groovy:150)                        
        at com.tlc.worx.company.CompanyQuestion.refresh(CompanyQuestion.groovy)                                                                  
        at com.tlc.worx.company.CompanyQuestion$refresh.call(Unknown Source)                                                                     
        at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)                                                 
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:110)                                                 
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:114)                                                 
        at com.tlc.worx.checklist.CompanyQuestionController$_index_closure1$_closure2$_closure3.doCall(CompanyQuestionController.groovy:49)      
        at com.tlc.worx.checklist.CompanyQuestionController$_index_closure1$_closure2$_closure3.doCall(CompanyQuestionController.groovy)         
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)                                                                           
--                                                                      

在数据库中搜索被引用的记录号只会在完全不相关的字段和 Tally 表中显示它:

(请注意,出现错误的页面与丢失的记录本身无关,仅与可能与 CompanyQuestion 相关但当前不相关的对象有关)。

我怀疑 Hibernate 缓存问题,特别是因为这与删除记录同时发生。此外,将相同的数据库迁移到另一个环境进行测试不会在新环境中产生相同的错误——证实了我的理论,即这与特定于环境的缓存有关。但奇怪的是,在原始环境中重新启动 Tomcat7(应用程序在 Tomcat 上运行)并不会导致问题消失。 Hibernate配置如下:

hibernate {
    cache.use_second_level_cache = true
    cache.use_query_cache = false
    cache.region.factory_class = 'org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory' // Hibernate 4
    singleSession = true // configure OSIV singleSession mode
    flush.mode = 'auto'       // pre-Hibernate4 default behavior was auto, so we'll stick with that for now. See https://grails.org/2.4.3+Release+Notes
}

重新启动并没有导致问题消失,这让我摸不着头脑——即使在 Tomcat 重新启动之间,这种正常的 Hibernate 行为是否也会永久缓存内容?我在这里完全错过了标记吗?我的下一步是在禁用二级缓存的第一个环境中运行应用程序,但我也希望获得社区反馈,我至少在我的理论方面处于正确的轨道上——这似乎很疯狂。任何建议/反馈表示赞赏!

【问题讨论】:

    标签: sql-server hibernate grails


    【解决方案1】:

    因为我最终发现了问题,所以想关闭它。

    我们的应用程序利用 ElasticSearch 编译一组数据来查询搜索。我们总是在应用程序重启时重新索引 ElasticSearch,之前没有遇到过这个问题,但是我了解到重新索引操作并不总是完全按照我们想要做的,实际上可以将旧数据索引为新记录,导致重复或好坏参半的记录。

    我的问题中的错误发生在从以前的重新索引中遇到“坏”、陈旧的记录之一时。在重新索引之前清除所有 ElasticSearch 索引解决了该问题。

    【讨论】:

      猜你喜欢
      • 2011-05-09
      • 1970-01-01
      • 2018-10-07
      • 2013-10-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多