Когда пессимистический замок выпущен в рельсах?
Предполагая, что я делаю что-то подобное (из Руководство по поиску активной записи)
Item.transaction do
i = Item.first(:lock => true)
i.name = 'Jones'
i.save
end
Является ли блокировка автоматически выпущенной в конце транзакции? Я просмотрел руководство по активному запросу и ActiveRecord:: Locking:: Pessimistic docs и не смог найти, где он явно говорит, где блокировка освобождается.
Ответы
Ответ 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/, похоже, предполагает, что структурная структура этого метода будет автоматически разблокирована.