ActiveRecord:验证和写入数据库之间的并发访问

时间:2012-11-07 11:45:58

标签: ruby-on-rails database ruby-on-rails-3 activerecord transactions

假设我的在线图书商店的数据模型如下:

enter image description here

在创建新订单之前,我想确保库存中有足够的商品,所以我有这样的方法

def ensure_enough_in_stock
    errors.add(:quantity, "not enough in stock") if quantity > book.stock
end

为了确保在保存到数据库之前调用此方法,我使用了验证:

validate :ensure_enough_in_stock, :on => create

总而言之,当我创建订单时:

  1. 调用验证方法
  2. 将新订单写入数据库(如果验证通过)
  3. 如果在1.和2.之间,另一个进程(并发访问,另一个线程......)对同一本书的stock属性执行修改会发生什么?是否提出了异常?

    更一般地说,如何处理验证和保存之间发生事件的情况?

    我认为我也应该对数据库进行验证,但我不知道它会对性能产生什么影响。是否有一种聪明的方法来处理这种情况?

    修改

    按照here解释锁定事务会阻止对库存的写入访问,但如果我在Book模型中也有“已发布”属性,可以采用“公共”或“私有”值,并且会发生什么情况,以及那么我想确保你不能买一本私人的书。

    但是,与外部流程可以更改股票价值的方式相同,公布的价值也可以改变:在这种情况下,锁定不会有任何帮助,是吗?

    enter image description here

1 个答案:

答案 0 :(得分:2)

Rails通常会在事务中包装验证并保存。因此,您唯一需要做的就是在ensure_enough_in_stock中使用锁定运行查询。锁定将阻止数据被其他请求更改。有关如何使用锁定进行查询,请参阅this