我们开发了一个 Grails 2.0 应用程序,它以前可以在 MySQL 上顺利运行
我们一直在要求我们的管理员切换到他们喜欢的 PostgreSQL
我们为应用程序添加了许多新功能,包括现在导致我们问题的一个:异步第三方 Web 服务请求
所以,我们创建了一个域对象,我们称之为问题。使用afterInsert
闭包Resource
创建 a,以便稍后存储对外部 Web 服务的调用结果。
class Question implements Serializable {
static hasMany = [resources: Resource]
static constraints = {
resources(nullable: true)
}
def afterInsert() {
Resource.withNewSession {
Resource txt = Resource.create(null)
this.addToResources(txt)
}
}
Resource retrieveResource(){
return this.resources.find{ it instanceof Resource }
}
static Question create(Map params) throws SaveDomainException {
//question creation
}
}
我们创建这样的问题:
//first we create question and save it
def question = Question.create(params)
question.save(flush:true, insert:true)
getThirdPartyService().doCallAsync((int)req.retrieveResource().id)
并且ThirdPartyService
作为一种方法doCallAsync
产生一个ExecutorService
(通过 executors grails 插件获得,因此这不是可怕的“Hibernate Session - Thread”问题),它Resource.get(res_id)
使用如上所示获得的 Id执行一个简单的
问题在于,使用 PostgreSQL 和pooled = true
inDataSource.groovy
时,get
有时返回 null,有时返回资源对象。
我们测试了 3 个不同的请求: a get(id)
、 afindById(id)
和executeQuery
带有 select 的 an。
更奇怪的是,上面三行在同一个方法中,有时我们会得到不同的结果。三个中只有一个返回 null,或者三个返回 null,或者没有(我记得这是预期的行为)
我们打开了PostgreSQL查询日志看看是不是Hibernate缓存问题,但是这3个请求都出现在了日志中,所以hibernate每次都命中数据库。我们看到插入了具有正确 ID 的资源,然后是提交,然后是三个选择(提供了正确的资源 ID)
有没有人暗示我们将进一步测试以查看此错误来自何处?(我们试图改变连接池,没有运气)
最后一件事,如果我们Thread.sleep(1000)
在请求之前添加一个(这是血淋淋的,但仅用于测试目的 ;-) ),一切都会顺利进行。所以,这似乎是 postgres 进程之间的可见性问题,但我们不知道如何解决这个问题