multithreading - chalice "Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect)"

标签 multithreading grails grails-orm database-concurrency

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
    }
}

它在“deflockedDogInstance = 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]

上面的设计非常简单,在 Owner 和 Dog 之间存在多对多关系:

狗类:
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。

有什么建议吗?

最佳答案

好的,这里有很多事情要做,我打赌你可以处理掉大部分。因此,与其尝试修复它,不如将其分解到最低限度并从那里开始:

  • 您的服务方法不应该是静态的。
  • 您的服务已经是事务性的,所以 withNewTransaction()可以去。你也不需要冲洗。
  • 无需同步服务方法。
  • 您无需锁定 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
        }
    }
    

    看看这能带你走多远。您甚至可以删除所有者锁定。

    关于multithreading - chalice "Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect)",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35734309/

    相关文章:

    java - 在指定的超时后从一个线程执行多个 Runnable

    c# - Web请求突然停止工作

    apache - Grails + Tomcat + Apache 切换到 HTTPS 时出现错误

    grails - 升级到Grails 4:Spring Security InerceptUrlMap无法基于层次结构运行

    hibernate - Grails 和后台任务

    multithreading - 通用线程安全属性

    c++ - 在 C++ 中使用 Boost Threads 的基本程序的问题

    oracle - Tomcat 上的 Grails Oracle - JNDI 配置 - InstanceAlreadyExistsException 等错误

    sorting - Grails 标准排序和分页

    hibernate - 在 Grails 外部使用 GORM 时找不到 session 错误