行级锁定在rails / mysql中无法正常工作

时间:2013-08-20 05:56:50

标签: mysql ruby-on-rails activerecord locking

我有以下关系

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语句。当然有多个进程在运行,但我认为锁会解决这个问题。看起来在事务块完成之前会给出锁定。

可能锁的工作方式与我预期的不同。任何见解都会非常有用。

感谢。

1 个答案:

答案 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秒后)。