Подтвердить что ты не робот

Когда пессимистический замок выпущен в рельсах?

Предполагая, что я делаю что-то подобное (из Руководство по поиску активной записи)

Item.transaction do  
  i = Item.first(:lock => true)  
  i.name = 'Jones'  
  i.save 
end 

Является ли блокировка автоматически выпущенной в конце транзакции? Я просмотрел руководство по активному запросу и ActiveRecord:: Locking:: Pessimistic docs и не смог найти, где он явно говорит, где блокировка освобождается.

4b9b3361

Ответ 1

Блокировка не является функцией рельсов, она просто добавляет оператор запроса в запрос, который будет зависеть от используемой базы данных. Пессимистическое блокирование воспринимает "пессимистическое" мнение, думая, что каждый запрос подвержен коррупции. Таким образом, он блокирует выбранные строки, пока вы не закончите транзакцию . поэтому Lock > query > unlock. Хотя это довольно согласованная база данных для базы данных, может быть полезно прочитать документацию по базе данных, которую вы используете для любых сведений о конкретной базе данных, которые вы должны знать.

Вот хороший поток оптимистической и пессимистической блокировки, которая объясняет это лучше, чем я могу. Оптимистическая и пессимистическая блокировка

Ответ 2

Да, блокировка автоматически снимается в конце транзакции, потому что этот вид блокировки применим только к транзакциям. Блокировать запись таким способом (пессимистическая блокировка) вне транзакции не имеет смысла.

Пессимистичные блокировки применяются на уровне БД.

Ниже приведено описание с примерами для mysql: http://dev.mysql.com/doc/refman/5.0/en/innodb-lock-modes.html

Ответ 3

Я признал проблему с пессимистической блокировкой внутри транзакции во время тестов rspec. По какой-то причине в разных системах (я обнаружил это из-за того, что CI не смог запустить spec) запись все еще заблокирована и не может быть получена.

Итак, код и пример rspec приведены ниже.

class FooBar
  def foo
    Model.with_lock do
      model.update(bar: "baz")
    end
  end
end

красный пример

it "updates with lock" do
  expect { Foobar.foo }.to change { model.reload.bar }.to("baz")
end

но правильный зеленый пример должен выглядеть так

it do "updates with lock" do
  Foobar.foo
  expect(model.reload.bar).to eq("baz")
end

Ответ 4

Я считаю, что вам нужно, чтобы блок "обеспечить" был уверен, что блокировка выпущена.

http://ruby-doc.org/core/classes/Mutex.src/M000916.html имеет:

  def synchronize
    lock
    begin
      yield
    ensure
      unlock
    end
  end

http://yehudakatz.com/2010/02/07/the-building-blocks-of-ruby/, похоже, предполагает, что структурная структура этого метода будет автоматически разблокирована.