鉴于以下模型和MySQL InnoDB表:
class User < ActiveRecord::Base
has_many :things, dependent: :destroy, inverse_of: :user
end
class Thing < ActiveRecord::Base
MAX_THINGS_PER_USER = 5
belongs_to :user, inverse_of: :things
# some other validations which read from the DB
# ...
validate :thing_count_within_limit, on: :create
def thing_count_within_limit
if self.user.things.count >= MAX_THINGS_PER_USER
errors.add(:base, "Exceeded thing limit")
end
end
end
当我在(几乎)完全相同的时间为已经有4个Thing
个实例的给定User
创建2个Thing
个实例时,根据我的理解,可能会发生{{{ 1}}最终会有6个User
个实例,因为包含验证的创建都包含在一个事务中,并且在此事务中读取的第一个DB会在DB上创建一个快照视图,因为默认读取模式为{{1 }}。这可能导致其各自事务内的两个验证读取计数为4,因此两个创建都有效,并且两个Thing
实例都存储在DB中,而READ REPEATABLE
有6个不需要的实例。
克服这种竞争条件的首选方法是什么?
我的方法是锁定关联的Thing
模型:
User