2012-07-26 27 views
9

Railsアプリケーションでいくつかの未加工SQLを実行する必要があります。クエリは、トランザクション内で実行される場合、暗黙のコミットを引き起こします。私たちはInnoDBでMySQLを使用しています。テーブルを作成します。Rails/ActiveRecordでトランザクション外でデータベース操作を実行する方法

ActiveRecord::Base.connection.executeでクエリを実行すると、implict commitが発生しますが、これは問題です。

私はクエリを実行するために別の接続が必要なように感じます。 ActiveRecordはこれを提供できますか?私は、複数のデータベースに接続することについて議論したが、同じデータベースへの複数の接続は検討していない。

ソリューションには、より良い方法がある場合はActiveRecordが必要ありません。

私たちのRailsとActiveRecordのバージョンは3.2.3です。

答えて

16

データベース接続は、あなたがあなたの利点に使用することができ、(これは基本的にスレッドの安全のために必要とされる)、スレッドごとに行われますレール4の場合、activerecordは自動的にこのようにして作成された接続を自動的に刈り取ることはありません。接続が漏れないようにするには、接続をプールに戻す必要があります。マット・コネリーが示すように、これを行う最も簡単な方法は、ブロックの最後にバックでの接続をチェックしますwith_connection方法を使用することで、たとえば

Thread.new do 
    ActiveRecord::Base.connection_pool.with_connection do 
    ... 
    end 
end 
+0

私はあなたがより良い問題を理解したと思う:) – PriteshJ

+1

終了時に接続プールに接続を戻すことを確認してください! –

+0

よろしくお願いします。答えは古くなった –

1

DDLおよびいくつかのより多くのクエリは、そう、彼らはあなたがCOMMITを行っていたかのように、これらは暗黙のうち、現在のセッションでアクティブなすべてのトランザクションを終了mysqlのドキュメント

http://dev.mysql.com/doc/refman/5.1/en/implicit-commit.html

ごとにロールバックすることはできません暗黙のコミットを発射します文を実行する前に

このようなクエリがない場合は、SAVEPOINT機能を使用できます。 (This does not work with DDL statements

ポイント、より多くの詳細については、

ActiveRecord::Base.transaction do 
    # ... 
    ActiveRecord::Base.transaction(:requires_new => true) do #creates save point 
     # perform task 
     # if error occurs rollbacks only till the save point. 
    end 
    end 

チェックrails docを保存使用するサブトランザクションを作成するのに役立ちます、アクティブ・レコード内のオプションがあります。例

ActiveRecord::Base.transaction do 
    # ... 
    Thread.new do 
    ActiveRecord::Base.connection.execute "..." # in a new connection 
    end.join 
end 

としてのために、ちょうど別のスレッドでコードを実行します。

+0

著者は疑問「のActiveRecord :: Base.connection.executeから、常に暗黙的にトランザクションをコミット(例えばテーブルを変更)します文 –

+0

@FrederickCheungについて話している:それを行うための最も簡単な方法は、このようなものです暗黙のコミットを引き起こしますが、これは問題です。彼自身がトランザクションを明示的に制御したいと考えさせています。私が間違っている場合私を修正してください – PriteshJ

2

のためにあなたの中に、接続を使用する場合にすることが重要です終了時に接続プールに接続を戻すスレッド。

Thread.new do 
    ActiveRecord::Base.connection_pool.with_connection do |connection| 
    connection.execute "..." 
    # ensures the connection is returned to the pool when the thread is done.   
    end 
end.join 
関連する問題