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 "分離が行われ、その後分離がデフォルトに戻ります。

私の質問は次のとおりです。トランザクションブロックが常に同じセッションで実行されることを確認できますか?また、同じセッションで最初のステートメントと2番目のステートメントの間に他のトランザクションが発生しないことを確認できますか?

私はこのトピックについてGoogleに挑戦しましたが、私がRailsに慣れてきたので、私にこれを明らかにする説明は見つかりませんでした。どんな助けもありがとう!

ありがとうございました!

答えて

2

「はい」であなたの質問にすべて回答できると思います。 Rails 3.2でも、データベースへの接続はconnection poolによって管理されています。このプールは、各スレッドが専用の接続をDBに確実に持ちます。プールは、スレッドごとに固有のスレッドIDに基づいてスレッドに接続を割り当てます。詳細はdocsをお読みください。

私は、2つのスレッドが同時に接続を共有することはできないと考えて、同時に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