我有以下关系
parent has_many children
child belongs_to parent
以下代码块
ActiveRecord::Base.connection.transaction do
lock_acquired = true
if child.parent.lock! and child.parent.status == 1
child.parent.update_attributes(:status => 2)
else
lock_acquired = false
end
if lock_acquired
# other code follows here
end
end
上面的代码块用于确保只有一个孩子能够一次更改父状态,从而锁定!方法和状态检查表达式。但不知怎的,它破碎了。即使父级状态由其中一个子级更改为2,另一个子级也能以某种方式通过if语句。当然有多个进程在运行,但我认为锁会解决这个问题。看起来在事务块完成之前会给出锁定。
可能锁的工作方式与我预期的不同。任何见解都会非常有用。
感谢。
答案 0 :(得分:0)
我不太清楚为什么你的更新代码不起作用,但有一个奇怪的事情:你使用lock!
就像它返回一个真/假值,但它只能永远返回模型实例本身(如果获取了锁)或引发错误(如果获取锁定超时)。这意味着lock_acquired
只有在获得 的锁时才会设置为false
,但父级的状态不等于1
。
此代码可能更具可预测性:
child.parent.with_lock do
if child.parent.status == 1
child.parent.update_attributes(:status => 2)
end
# other code follows here
end
请注意with_lock
的行为与lock!
类似 - 要么执行块,要么抛出锁定超时错误(在默认MySQL设置下等待50秒后)。