2016-09-13 94 views
1

我們有一個高度併發的Grails應用程序,有幾個工作線程嘗試更新同一個域對象Message,但悲觀鎖定解決方案在服務中使用靜態實現(事務設置爲false)鎖Message.lock(msg.id)導致HibernateOptimisticLockingFailureException的許多實例。Grails Gorm靜態鎖定導致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)

任何策略,我應該考慮(比捕捉異常等)? isDirty()isEmpty()

+0

我應該添加從設計的角度來看,圍繞兩個線程嘗試更新包括Status在內的任何字段的相同消息,如果響應是200,那麼消息應該始終設置爲softDelete。對消息的任何其他更新都變得無關緊要,並且可能會丟失或覆蓋。 –

回答

0

這是一個很好的和非常詳細的article關於這個問題。我有完全一樣的問題,因爲你和我解決它使用悲觀鎖定,即

  • 啓動事務
  • 獲取對象,並通過靜態lock()方法鎖定
  • 更新對象
  • 提交交易

看起來您正在做類似的事情,但我無法分辨您是否在交易中執行此操作,因爲一方面您說

the pessimistic locking solution implemented in the service (with transactional set to false)

但是另一方面,代碼似乎在withTransaction內執行。悲觀鎖定方法必須在事務中執行。

+0

感謝您的文章。是的,這是一個交易,因爲我們正在使用withTransaction。我們有其他方法不是事務性的。 –