似乎没有成为最终解决并发问题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的是。
任何建议?
OK,你已经得到了很多会在这里,其中大部分我敢打赌,你可以配置的。因此,而不是试图修复它,让我们撕裂下来到最低限度,并从那里继续:
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
}
}
看多远,带你。你甚至可以去除业主锁。
除了什么@灵光罗莎说,如果有发生太多的并发更新,你能不能也确保在保存之前调用“刷新”(对老板)? (repeatable reads方法)。
加入表增加不应该从这些虽然受到影响。只有当正在尝试一些狗被“重新添加”到同一业主,可能会导致问题。
另一种方法(而不是在这种情况下,但)如果只有一个或两个列进行更新,你可以使用普通的SQL。