11

Railsアプリで生のSQLを実行する必要があります。クエリがトランザクション内で実行された場合、クエリは暗黙のコミットを引き起こします。InnoDBでMySQLを使用しており、クエリにはcreatetableなどが含まれます。

を使用してクエリを実行するActiveRecord::Base.connection.executeと、問題となる暗黙のコミットがトリガーされます。

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

より良い方法があれば、ソリューションにActiveRecordを含める必要はありません。

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

4

3 に答える 3

20

データベース接続はスレッドごとに実行され(これは基本的にスレッドセーフのために必要です)、これを有利に使用できます。たとえば、コードを別のスレッドで実行するだけです。

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

Rails 4以降、activerecordはこの方法で作成された接続を自動的に取得しなくなりました。接続のリークを回避するには、接続をプールに戻す必要があります。Matt Connellyが示唆しているように、これを行う最も簡単な方法はwith_connection、たとえば、ブロックの最後で接続をチェックインする方法を使用することです。

Thread.new do
  ActiveRecord::Base.connection_pool.with_connection do
    ...
  end
end
于 2012-07-26T18:25:12.057 に答える
4

スレッドで接続を使用する場合は、完了時に接続を接続プールに戻すことが重要です。これを行う最も簡単な方法は次のとおりです。

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
于 2014-08-11T00:48:22.220 に答える
2

DDlおよびその他のいくつかのクエリは、暗黙のコミットを起動するため、mysqlのドキュメントに従ってロールバックできません。

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

これらは、ステートメントを実行する前にCOMMITを実行したかのように、現在のセッションでアクティブなトランザクションを暗黙的に終了します。

間にそのようなクエリがない場合は、SAVEPOINT機能を使用できます。(これはDDLステートメントでは機能しません

アクティブレコードには、セーブポイントを使用するサブトランザクションの作成に役立つオプションがあります

   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のドキュメントを確認してください。

于 2012-07-26T18:16:46.683 に答える