由于竞争条件,避免超额预订

时间:2017-09-19 01:36:29

标签: mysql ruby-on-rails activerecord

我们正在考虑预订系统,其中涉及两个模型:StoreReservationStoremax_seatsReservationguests_count列。

为避免超量预订,我们已实施验证。如果超量预订,则回滚事务。但我不确定这是否足以抵御竞争条件。

像这样:

class Store < ActiveRecord::Base
  has_many :reservations
  validates :max_seats, presence: true, numericality: true
end

class Reservation < ActiveRecord::Base
  belongs_to :store
  validates :guests_count, presence: true, numericality: true

  after_create do
    total_seats_taken = reservation_slot.reservations.sum(&:guests_count)
    unless total_seats_taken <= store.max_seats
      raise ActiveRecord::Rollback
    end
  end
end

我怀疑这种scnenerio仍然可能发生,即使它很少见:

假设客户A和客户B分别在同一时间单独预订6个席位,max_seats设置为10.如果客户A的交易在客户B执行之前提交{{ 1}}回调,after_create异常被引发,并且未创建客户B的记录,这是预期的。但是,如果在提交客户A的交易之前执行ActiveRecord::Rollback回调,我认为这将导致超额预订。

A开始交易 - &gt; A执行after_create - &gt;提交交易 - &gt; B执行after_create:B遇到after_create例外

A开始交易 - &gt; A执行ActiveRecord::Rollback - &gt; B执行after_create - &gt;提交交易:超量预订!!

如果你能分享任何见解,我将不胜感激。谢谢。

1 个答案:

答案 0 :(得分:-1)

为什么不直接使用before_create?你可以按照自己的方式去做,但是为什么你会想要开始将它写入数据库并在不需要时引发异常?