如何锁定表以防止在Rails中使用记录创建?

时间:2019-04-04 14:37:20

标签: ruby-on-rails architecture mariadb data-integrity

Rails提供了几种锁定单个记录的方法。 Active Record Query Interface guide中对此进行了描述。但是,我目前处于以下情况,锁定现有记录不会成功:

我有一个 Letter 模型,该模型具有可选的 mailing_nr 属性。对于邮件,我将获取最大的 mailing_nr 并添加一个。然后,在事务中创建一堆字母,因为所有字母应同时保存,或者根本不保存。

想象一下这样一种情况:两个用户在同一时间生成邮件。它们都将获取最高的 mailing_nr (我将以6为例)。当两个进程都保存其记录时,它们将以相同的 mailing_nr 结尾。

如何防止上述情况?我想锁定整个表,以防止其他进程进行读写。但是我不知道有任何Rails方法可以做到这一点。

这是我的代码示例:

# app/models/letter.rb
def self.create_mailing(template, report, options = {})
  options = options.dup
  options[:mailing_nr] = (Letter.maximum(:mailing_nr) || 0) + 1

  letters = nil
  transaction do
    letters = report.fetch_records.map do |record|
      new_with_template(template, record, options).tap(&:save!)
    end
  end

  letters
end

1 个答案:

答案 0 :(得分:0)

您可以像这样使用Rails Lock

letter = Letter.find(1)
letter.with_lock do
    #Do whatever you want, You have only single access here. No two persons can access this at a time 
end

注意请务必仔细阅读提供的链接,因为您可能会在此处找到不同的方法,这可能会更好地解决您的特定问题。

更新:您可以使用this gem,但会被警告可能导致死锁。