0

У меня есть следующий фрагмент кода в приложении Rails 3.2 + MySql:Rails ActiveRecord сеанс связи

ActiveRecord::Base.connection.execute("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED") 
ActiveRecord::Base.transaction do 
       @book = ActiveRecord::Base.connection.execute("select * from books limit 1") 
end 

Насколько я понимаю, что первое утверждение приведет к следующему транзакции внутри одного сеанса, чтобы быть в " READ UNCOMMITTED ", а затем изоляция вернется к умолчанию.

Мои вопросы: могу ли я быть уверенным, что блок транзакций всегда будет выполнен в том же сеансе? Кроме того, могу ли я быть уверенным, что никакая другая транзакция не будет проходить в том же сеансе между первым и вторым операциями?

Я пробовал Google для этой темы, но поскольку я новичок в Rails, я не мог найти объяснений, которые бы это поняли для меня. Любая помощь будет оценена!

Спасибо!

ответ

2

Я думаю, что на все ваши вопросы можно ответить «ДА». Даже в Rails 3.2 соединения с базой данных управляются connection pool. Этот пул гарантирует, что каждый поток будет иметь свое собственное выделенное соединение с БД. Пул назначает подключения к потокам на основе их идентификаторов потоков, которые уникальны для каждого потока. Прочтите docs для получения дополнительной информации.

Таким образом, я думаю, что не должно быть возможным, чтобы два потока могли совместно использовать соединение и, следовательно, сеанс MySQL в одно и то же время. Кроме того, должно быть гарантировано, что транзакция всегда будет вызываться с использованием того же соединения (то есть в том же сеансе), что и код установки уровня изоляции.

Кстати, если вы использовали Rails 4 или выше, вы можете добиться такого же поведения, используя метод transaction. К сожалению, установка уровней изоляции не поддерживается таким образом в Rails 3. Таким образом, следующий пример на самом деле не будет работать в вашем конкретном сценарии:

Book.transaction(:isolation => :read_uncommitted) do 
    @book = Book.first 
end 
# => SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED 
# BEGIN 
#  SELECT `books`.* FROM `books` ORDER BY `books`.`id` ASC LIMIT 1 
# COMMIT 
+0

Спасибо. Это помогает! Да, похоже, что у Rails 4 есть лучшее решение для этого, но, к сожалению, сейчас я не могу перейти на Rails 4 с текущим проектом. –

+0

Следующий вопрос: нужно ли обертывать заявление в транзакционном блоке, как в коде? Будет ли изоляция по-прежнему работать должным образом, если я просто выполню sql-оператор без транзакционного блока? –

+1

Да, как объяснено [здесь] (http://dev.mysql.com/doc/refman/5.7/en/set-transaction.html), параметр изоляции действителен для следующего блока транзакций. Даже установка изоляции на уровне сеанса действительна только для всех последующих транзакционных блоков. – BoraMa

 Смежные вопросы

  • Нет связанных вопросов^_^