Rails 3 - 潜在竞争条件?

时间:2011-07-20 21:13:42

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

我有一个非常简单的Rails 3应用程序,用户可以在特定日期保留有限数量的同类项目之一。我试图避免竞争条件,其中两个人保留特定日期的最后一个项目。模型(简化)如下:

class Reservation < ActiveRecord::Base
  belongs_to :user
  attr_accessible :date
  MAX_THINGS_AVAILABLE = 20

  validate :check_things_available

  def check_things_available
    unless things_available? errors[:base] << "No things available"
  end

  def things_available?
    Reservation.find_all_by_date(date).count < MAX_THINGS_AVAILABLE 
  end           
end

通过current_user.reservations.build(params[:reservation])

在控制器中创建预订

感觉有更好的方法可以做到这一点,但我无法完全理解它是什么。任何有关如何防止竞争状况的帮助将不胜感激。

2 个答案:

答案 0 :(得分:0)

不确定这会回答您的问题,但它可能会指向您找到解决方案:

http://webcache.googleusercontent.com/search?q=cache:http://barelyenough.org/blog/2007/11/activerecord-race-conditions/

(原始网站似乎已关闭,因此这是指向Google缓存的链接)

该页面上的结论是乐观锁定和行级别锁定不是创建时竞争条件的解决方案,只是在更新时。

作者建议使用db约束重新实现find_or_create。

另一个建议是将事务隔离级别切换为“可序列化”应该可以工作,但是没有关于如何在Rails中执行此操作的信息。

答案 1 :(得分:0)

只需使用redis locker

等任何锁定机制
RedisLocker.new("thing_to_sell_#{@thing.id}").run do
  current_user.create_reservation(@thing) or raise "Item already sold to another user"
end