with_lock会锁定块中的所有内容吗?

问题描述

with_lock是锁定块中的所有模型还是仅锁定模型本身?例如,在下面的示例中,item内的所有with_lock模型是否被锁定,还是entry模型被锁定了?

class Entry < ApplicationRecord
  enum state: [:pending,:posted]
    
  has_many :items,dependent: :destroy
 
  def post!
    with_lock do
      return unless pending?
      items.each { |i| i.post! }
      self.posted!
    end
  end
end

解决方法

with_lock在单个实例上获得行级悲观锁。 with_lock只是将lock和transaction语句合并为一个,因此等效于:

Entity.transaction do
  entity_instance.lock!
end

您在模型内部调用with_lock,因此您实际上在执行self.with_lock。也就是说,您正在获得Entity当前实例的锁。单独的Item记录不会获得锁定,除非您也明确地锁定了它们。但是,对它们所做的更改的确包含在同一父事务中。