Лок на запись

October 27, 2014

Бывает, что при обновлении строчки в базе хочется сделать серию сложных операций с зависимыми записями и желательно, чтобы паралельные потоки в это время не мешали.

В PostgreSQL есть замечательный способ блокировки SELECT FOR UPDATE, который мне как-то подсказал Иван. Если запустить 2 транзакции и в обеих вызвать SELECT FOR UPDATE, то вторая транзакция будет ожидать окончания первой.

В Рейсл такие запросы удобно упакованы в методе with_lock .

class User < ActiveRecord::Base
  def do_some_tricky_calculations
    with_lock do
      self.name = "Tricky Dude"
      # update a lot different records
      save!
    end
  end
end

В логах мы увидем такой же FOR UPDATE, как мы это делали вручную:

Как и в любой хорошем приеме, здесь нужна мера. Если блокировать базу часто и надолго, то производительность упадет сильно.

comments powered by Disqus