我在Grails中使用锁时遇到了一些问题。
情况如下:
我有一个User类,然后是另一个具有belognsTo = User Property的Class UserProperty。
现在为了避免用户同时修改此属性,我想锁定用户,然后修改/添加/删除新属性。
但锁似乎不起作用,因为在这两种情况下请求都会失败。伪代码看起来像这样:
User.lock(userId)
log.info "Starting modifiying properties"
addRemoveOrChangePropertiesToUser(userId)
log.info "Finsih modifing properties"
User.save(flush: true)
我期待的行为是,第一个请求通过并记录所有内容。直到那个(因为用户被锁定),第二个请求等待,然后对属性进行更改。
根据日志文件,我看到一个完全不同的行为。两个请求都在没有任何等待时间的情况下处理(almos simultationiusly)。
你有什么想法,我做错了什么?我是否错过了解与数据库锁定相关的一些概念?我怎样才能达到预期的行为?
谢谢, 尼古拉斯
答案 0 :(得分:4)
我遇到了类似的问题,我的功能是在控制器中。我认为其他线程一旦命中.lock语句就应该被阻止,但那并没有发生。在交易中包装整个事情为我解决了问题。
这样的事情:
User.withTransaction {
User.lock(userId)
log.info "Starting modifiying properties"
addRemoveOrChangePropertiesToUser(userId)
log.info "Finsih modifing properties"
User.save()
}
事后看来,这是有道理的。我怀疑交易是否需要提供明确的划分(工作单元),否则GORM / hibernate如何知道何时可以释放锁定?
控制器方法具有开放会话但不包含在事务中。默认情况下,服务方法包含在事务中,我怀疑我们不会在那里看到这个问题。
答案 1 :(得分:0)
我不确定锁是如何工作的。我的理解是它从OTHERS锁定实体,当他们从休眠会话中获取实体时更新同一个实例。
答案 2 :(得分:-2)
我不确定你是否正确实现了这一点。我认为你需要获得一个实例 - 然后将其锁定为......
def instance = Thing.get(1)
instance.lock()
然后尝试修改锁定的实例。