2016-09-13 1 views
1

複数のワーカースレッドが同じドメインオブジェクトMessageを更新しようとしているが、同時実行性が高いGrailsアプリケーションがありますが、静的ロック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

レスポンスが200ならば、メッセージを常にsoftDeleteに設定する必要があります。ステータスを含むすべてのフィールドに対して同じメッセージを更新しようとする2つのスレッドについて、デザインの観点から追加する必要があります。メッセージに対するその他の更新は無関係になり、失われたり上書きされたりする可能性があります。 –

答えて

0

この問題については、articleと非常に詳細です。私はあなたとまったく同じ問題を抱えていたと私は悲観的ロックを使用して、それを解決した、すなわち

  • トランザクションを開始
  • オブジェクトを取得し、更新静的lock()メソッドを介して
  • それをロックしたオブジェクト
  • トランザクションをコミットしてください

あなたは何か似たように見えますが、一方であなたはトランザクションの中でそれをやっているかどうかわかりません。

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

しかし、コードはwithTransactionの範囲内で実行されているようです。ペシミスティック・ロッキング・アプローチは、トランザクション内で実行する必要があります。

+0

記事をありがとう。はい、withTransactionを使用しているため、トランザクションです。トランザクションではない他のメソッドがあります。 –

関連する問題