锁定Grails不起作用

锁定Grails不起作用,grails,locking,gorm,Grails,Locking,Gorm,在使用Grails中的锁时,我遇到了一些问题 情况如下: 我有一个User类,然后是另一个类UserProperty,它有一个belognsTo=User属性 现在为了避免用户同时修改这些属性,我想锁定用户,然后修改/添加/删除新属性 但锁似乎不起作用,因为在这两种情况下,请求都会失败。伪代码如下所示: User.lock(userId) log.info "Starting modifiying properties" addRemoveOrChangePropertiesToUser(use

在使用Grails中的锁时,我遇到了一些问题

情况如下:

我有一个User类,然后是另一个类UserProperty,它有一个belognsTo=User属性

现在为了避免用户同时修改这些属性,我想锁定用户,然后修改/添加/删除新属性

但锁似乎不起作用,因为在这两种情况下,请求都会失败。伪代码如下所示:

User.lock(userId)
log.info "Starting modifiying properties"
addRemoveOrChangePropertiesToUser(userId)
log.info "Finsih modifing properties"
User.save(flush: true)
User.withTransaction {
    User.lock(userId)
    log.info "Starting modifiying properties"
    addRemoveOrChangePropertiesToUser(userId)
    log.info "Finsih modifing properties"
    User.save()
}
我期望的行为是,第一个请求将通过并记录所有内容。在这之前(因为用户被锁定),第二个请求等待,然后对属性进行更改

根据日志文件,我看到了完全不同的行为。这两个请求都是在没有任何等待时间的情况下处理的(almos同时处理)

你知道我做错了什么吗?我是否理解了一些与db锁定相关的概念?我怎样才能达到期望的行为

谢谢,
尼古拉斯

我不确定你是否正确实施了这一点。我认为您需要获取一个实例,然后像

def instance = Thing.get(1)
instance.lock()

然后尝试修改锁定的实例

我不确定锁是这样工作的。据我所知,当其他人从hibernate会话获取实体时,它会将实体锁定在更新相同实例的位置。

我刚刚遇到了一个类似的问题,我的函数位于控制器中。我认为一旦点击.lock语句,其他线程应该被阻塞,但事实并非如此。将整个事情包装在事务中解决了我的问题

比如说:

User.lock(userId)
log.info "Starting modifiying properties"
addRemoveOrChangePropertiesToUser(userId)
log.info "Finsih modifing properties"
User.save(flush: true)
User.withTransaction {
    User.lock(userId)
    log.info "Starting modifiying properties"
    addRemoveOrChangePropertiesToUser(userId)
    log.info "Finsih modifing properties"
    User.save()
}
事后看来,我想这是有道理的。我怀疑事务需要提供一个明确的划分(工作单元),否则GORM/hibernate如何知道何时可以释放锁


控制器方法具有打开的会话,但未包装在事务中。默认情况下,服务方法被包装在事务中,我怀疑我们不会看到这个问题

MySQL,这有什么区别吗?为什么
user
是小写?您是在调用对象上的
lock(int-id)
方法,而不是静态类方法吗?不,很抱歉,只是拼写错误。。会马上更正吗Nicolas,您在这个表中使用了什么mysql存储引擎?InnoDB或MyISAM?嗨,Splix,我没有更改它,所以我假设它是mysql默认的。这有什么区别吗?那是伪代码。这个答案代码是Grails文档中提到的一个反模式。建议采用这种方式:
def instance=Thing.lock(1)
这很好,但最好将其移动到事务服务方法。