我们有一个高并发性的Grails应用程序,有多个工作线程试图更新同一个域对象Message,但是使用静态锁Message.lock(msg.id)
在服务中实现的悲观锁定解决方案(事务性设置为false)会导致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] with identifier [58653744]: optimistic locking failed; nested exception is org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.cds.healthdock.messaging.Message#58653744] at messaging.OutboxService$_pushMessageToPeer_closure8.doCall(OutboxService.groovy:442) at org.grails.datastore.gorm.GormStaticApi.withTransaction(GormStaticApi.groovy:815)
我应该考虑采取什么策略(除了捕获异常(exception))?
isDirty()
isEmpty()
最佳答案
这是有关此问题的出色且非常详细的article。我遇到了与您完全相同的问题,并且通过使用悲观锁定来解决了该问题,即
lock()
方法看起来您正在执行类似的操作,但是我无法确定您是否在交易中执行此操作,因为一方面您说
the pessimistic locking solution implemented in the service (with transactional set to false)
但是另一方面,该代码似乎在
withTransaction
中执行。悲观锁定方法必须在事务内执行。
关于hibernate - Grails Gorm静态锁定导致HibernateOptimisticLockingFailureException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39480276/