Grails的“行是由另一个事务更新或删除(或者未保存值的映射是不正确的)”

问题描述 投票:1回答:2

似乎没有成为最终解决并发问题Grails中(2.3.7)。我已经尝试了所有的建议,但是当我推的并发线程数,下面这段代码总是失败:

package simpledb

import grails.transaction.Transactional
import groovy.transform.Synchronized
import org.apache.commons.logging.LogFactory

@Transactional
class OwnerService {
    private static final myLock1 = new Object()
    private static final myLock2 = new Object()

    @Synchronized('myLock1')
    static public saveOwner(def ownerName) {
        def ownerInstance = null
        Owner.withNewTransaction {
            ownerInstance = Owner.findOrCreateByName(ownerName)
            ownerInstance.save(failOnError: true, flush: true)
        }
        ownerInstance
    }

    @Synchronized('myLock2')
    static public associateDog(def ownerId, def dogId) {
        def lockedOwnerInstance
        Owner.withNewTransaction {
            lockedOwnerInstance = Owner.lock(ownerId)
            def lockedDogInstance = Dog.lock(dogId)
            lockedOwnerInstance.addToDogs(lockedDogInstance)
            lockedOwnerInstance.save(failOnError: true, flush: true)
        }
        lockedOwnerInstance
    }
}

它失败就行了 “DEF lockedDogInstance = Dog.lock(dogId)”:

Error 500: Internal Server Error    

URI
      /simpledb/JsonSlurper/api
Class
      org.hibernate.StaleObjectStateException
Message
      Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [simpledb.Dog#111]

上述设计非常简单,那里的主人和狗之间的许多一对多的关系:

狗类:

package simpledb

class Dog {
    String name
    Breed breed = null
    Integer age = null
    static hasMany = [owners: Owner]
    static belongsTo = Owner
    static mapping = { owners lazy: false }
    static constraints = {
        name blank: false, nullable: false, unique: true
        breed nullable: true
        age nullable: true
    }
}

所有人类别:

package simpledb

class Owner {
    String name;
    static hasMany = [dogs: Dog]
    static mapping = { dogs lazy: false }
    static constraints = {
    }
}

仅供参考 - 数据库MySQL的是。

任何建议?

multithreading grails gorm database-concurrency
2个回答
1
投票

OK,你已经得到了很多会在这里,其中大部分我敢打赌,你可以配置的。因此,而不是试图修复它,让我们撕裂下来到最低限度,并从那里继续:

  1. 您的服务方法不应该是一成不变的。
  2. 您的服务已是事务性的,所以withNewTransaction()可以走了。你也不需要刷新。
  3. 有没有需要同步的服务方法。
  4. 你并不需要在Dog锁,因为你不改变它(将其添加到只Owner.dogs在连接表中创建一个记录)。

有了这些变化,你的服务最终看起来是这样的:

package simpledb

import grails.transaction.Transactional
import org.apache.commons.logging.LogFactory

@Transactional
class OwnerService {

    def saveOwner(def ownerName) {
        def ownerInstance = Owner.findOrCreateByName(ownerName)

        ownerInstance.save(failOnError: true)
        ownerInstance
    }

    def associateDog(def ownerId, def dogId) {
        def ownerInstance = Owner.lock(ownerId)
        def dogInstance = Dog.read(dogId)

        ownerInstance.addToDogs(dogInstance)
        ownerInstance.save(failOnError: true)
        ownerInstance
    }
}

看多远,带你。你甚至可以去除业主锁。


0
投票

除了什么@灵光罗莎说,如果有发生太多的并发更新,你能不能也确保在保存之前调用“刷新”(对老板)? (repeatable reads方法)。

加入表增加不应该从这些虽然受到影响。只有当正在尝试一些狗被“重新添加”到同一业主,可能会导致问题。

另一种方法(而不是在这种情况下,但)如果只有一个或两个列进行更新,你可以使用普通的SQL。

© www.soinside.com 2019 - 2024. All rights reserved.