Grails Gorm静态锁导致HibernateOptimisticLockingFailureException

Grails Gorm静态锁导致HibernateOptimisticLockingFailureException,hibernate,grails,gorm,Hibernate,Grails,Gorm,我们有一个高并发的Grails应用程序,几个工作线程试图更新同一个域对象Message,但服务中实现的悲观锁定解决方案(事务设置为false)使用静态锁Message.lock(msg.id)导致许多情况下出现HibernateOptimisticLockingFailureException Facility.withTransaction { if (resp?.status == 200) { Message msgCopy = Message.lock

我们有一个高并发的Grails应用程序,几个工作线程试图更新同一个域对象Message,但服务中实现的悲观锁定解决方案(事务设置为false)使用静态锁
Message.lock(msg.id)
导致许多情况下出现
HibernateOptimisticLockingFailureException

    Facility.withTransaction {
      if (resp?.status == 200) {
        Message msgCopy = Message.lock(msg.id)
        msgCopy.state = State.SoftDeleted
        msgCopy.save(flush: true)
      }
    }
静态锁定如何导致
HibernateOptimisticLockingFailure
?我的理解是,静态锁将读取最新的持久版本。这仅仅是另一个线程删除它的情况吗

完全错误:

[com.cds.healthdock.messaging.Message]带有标识符[58653744]: 乐观锁定失败;嵌套异常是 org.hibernate.StaleObjectStateException:行已由更新或删除 另一个事务(或未保存的值映射不正确): [com.cds.healthdock.messaging.Message#58653744] 在messaging.OutboxService$\u pushMessageToPeer\u closure8.doCall(OutboxService.groovy:442) 位于org.grails.datastore.gorm.GormStaticApi.withTransaction(GormStaticApi.groovy:815)


<任何策略(除了例外)我都应该考虑?code>isDirty()isEmpty()

下面是一篇关于这个问题的非常详细的文章。我的问题与您完全相同,我通过使用悲观锁定解决了它,即

  • 启动交易
  • 获取对象并通过static
    lock()
    方法锁定它
  • 更新对象
  • 提交事务
看起来你也在做类似的事情,但我无法判断你是否在交易中这样做,因为一方面你说

服务中实现的悲观锁定解决方案(事务设置为false)


但另一方面,代码似乎是在
withTransaction
中执行的。悲观锁定方法必须在事务中执行。

我应该补充一点,从设计角度来看,两个线程试图为任何字段(包括状态)更新同一消息,如果响应为200,则消息应始终设置为softDelete。对邮件的任何其他更新都将变得无关紧要,并且可能会丢失或被覆盖。感谢您的文章。是的,这是一项交易,因为我们使用withTransaction。我们还有其他非事务性的方法。