【问题标题】:Grails session handling in waiting thread with Hibernate and MySQL InnoDB使用 Hibernate 和 MySQL InnoDB 在等待线程中处理 Grails 会话
【发布时间】:2011-07-21 20:23:52
【问题描述】:

为了在我正在使用 Grails(和 GWT)开发的 AJAX 驱动的应用程序中实现客户端通知,我实现了一个服务方法,该方法将在收到信号之前一直阻塞。我正在使用监视器对象来等待信号。一旦发出信号,线程将在数据库中查询新对象,然后将实体返回给浏览器。

它在内存数据库上工作得非常好,但在我使用 MySQL 数据库连接器时却不像我预期的那样。会发生什么:每当我调用 findAllBy... 时,它只会找到在请求开始之前创建的对象。

我的服务方法的生命周期

  • 来自客户的请求
  • Grails 正在创建 Hibernate 会话
  • 为新对象服务查询数据库
  • 如果没有:等待
  • 传入信号:查询数据库中的新对象(DOES NOT GET NEW OBJECTS 使用 MySQL 时,与 memory db 一起工作正常)

mysql 查询日志按预期显示所有查询,但 findAllBy... 的结果只是一个空数组。

我禁用了查询和二级缓存。无论数据连接是否池化,行为都是相同的。

我做错了什么?我应该关闭休眠会话吗?冲洗吗?为我的查询使用交易?或者以某种方式强制使用 findAllBy... 方法来查询数据库?

【问题讨论】:

    标签: mysql hibernate session grails concurrency


    【解决方案1】:

    只是一个猜测,但这听起来像是您遇到幻读的事务隔离级别问题。您的服务是否需要是事务性的?如果没有在服务中设置transactional=false

    【讨论】:

    • 服务本身是事务性的=false,但由具有@Transactional 的服务调用。我不需要监控服务中的事务。
    • 我不是 100% 确定,但我相信 @Transactional 优先于服务上的事务属性并将传播事务。您可能想尝试将隔离级别更改为 ISOLATION_SERIALIZABLE 并查看是否可以解决问题。
    • 服务现在以非事务模式运行。但是,它仍然缺少一些更新。即使在 save(flush:true) 调用之后发出信号,它有时仍会在提交创建对象的事务之前查询数据库。
    • 是否有任何方法可以确定实体何时真正持久化并提交到数据库?
    • 我将您的帖子解释为意味着当您在 MySQL 中发出查询但不能通过您的服务通过 GORM 时,您可以看到提交。如果您没有使用 SQL 查看数据库中的数据,那么我会首先排除一堆更常见的事情。例如,保存是否实际工作或是否存在错误;会话刷新等
    【解决方案2】:

    我认为您需要在保存调用时刷新会话以获取您正在寻找的新对象,例如

    DomainOfFrequentlyAddedStuff.save(flush:true) 
    

    然后它们应该快速保存到数据库中,以便它们显示在您的 findAll() 查询中。

    【讨论】:

    • 我已经在使用 save(flush:true) - 我可以从 MySQL 日志中看出 INSERT 查询是在 SELECT 查询之前插入的。即使在一分钟后,findAllBy... 方法也会返回一个空数组。
    • 哦,好吧。您是否尝试过发出 get() 查询(按 id)?在您在命令行查看 db 以查看一些新插入的 id 之后。当然,这不是解决方案,但它可能会告诉您这是否是 GORM/Hibernate 动态查找器问题。
    • 我认为实际上只是在另一个事务的插入和提交之间执行了选择,而不是在那之后
    猜你喜欢
    • 1970-01-01
    • 2022-07-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-05
    • 1970-01-01
    • 2010-12-12
    • 1970-01-01
    • 2011-03-27
    相关资源
    最近更新 更多