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