hibernate - chalice : Select returns (randomly) null while row exists in PostgreSQL with connection pooling turned on

标签 hibernate postgresql grails connection-pooling

我们开发了一个以前在 MySQL 上顺利运行的 Grails 2.0 应用程序

我们的管理员一直要求我们切换到他们更喜欢的 PostgreSQL

我们为应用程序添加了一系列新功能,包括现在给我们带来问题的功能:异步第三方 Web 服务请求

因此,我们创建了一个域对象,我们称它为问题。使用 afterInsert 闭包,将创建一个 Resource,以便稍后存储对外部网络服务的调用结果。

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 和 DataSource.groovy 中的 pooled = trueget 有时返回 null,有时返回资源对象。

我们测试了 3 种不同的请求:get(id)findById(id) 和带有选择的 executeQuery .

更奇怪的是,上面三行在同一个方法中,有时会得到不同的结果。三个中只有一个返回 null,或者三个返回 null,或者没有(我记得这是预期的行为)

我们打开了PostgreSQL的查询日志,看看是不是Hibernate缓存的问题,但是3个请求都出现在日志中,所以hibernate每次都命中数据库。我们看到插入了具有正确 ID 的资源,然后是提交,然后是三个选择(提供了正确的资源 ID)

有没有人提示我们将进一步测试什么以查看此错误的来源? (我们尝试更改连接池,但没有成功)

最后一件事,如果我们在请求之前添加一个 Thread.sleep(1000)(这很血腥,但仅用于测试目的 ;-) ),所有运行都会顺利进行。所以,这似乎是 postgres 进程之间的可见性问题,但我们不知道如何解决这个问题

最佳答案

您花时间研究了这个问题并将其写成一个很好的问题,但遗漏了重要日志?

我推测您的保存和异步获取之间存在重叠事务。要么保存未提交,要么 get 在保存发生之前看到一致的快照。确保您在日志记录中启用了 process-id,或通过其他方式来区分连接并查看语句发生的顺序。


编辑:看起来像交易快照时间。

在 PostgreSQL 中,所有语句都在一个事务中(可能是隐式的并且只持续一个语句)。

默认模式是“Read Committed”,这意味着您可以看到事务期间发生的提交。

还有“可序列化”级别的选项,这意味着您(大部分)在事务开始时看到数据库的卡住快照。

有关更多信息,请参阅 the docs .

打开两个 psql 控制台并尝试一些变体,在一个中提交并在另一个中选择不同的隔离级别。您应该能够看到您的实时系统发生了什么。

关于hibernate - chalice : Select returns (randomly) null while row exists in PostgreSQL with connection pooling turned on,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11904717/

相关文章:

grails - grails database-migration-即使没有域模型更改,也会生成更改日志

java - 事务回滚后oracle undo sequence会增加吗?

sql - Hibernate HQL 相当于 Oracle 并行关键字

java - Hibernate,Spring - 没有在数据库中填充我的表

url - Grails URL映射 Controller

javascript - SSE失败:使用事件推送插件在grails中注册事件监听器后出现问题

java - 如何判断当前 session 是否脏?

java - 如何使用 Java 和 PostgreSQL 在 Web 应用程序中保存、检索和绘制图像?

ruby-on-rails - Ruby:如何将数组写入 postgresql?

sql - PostgreSQL:如何使用包含时间戳的字符列