2012-07-26 86 views
9

我需要在Rails應用程序中執行一些原始SQL。如果查詢在事務中執行,則該查詢將導致隱式提交。我們在InnoDB中使用MySQL,查詢將包含例如創建表格。如何在Rails/ActiveRecord事務之外執行數據庫操作

使用ActiveRecord::Base.connection.execute執行查詢會觸發implict commit,這是一個問題。

感覺就像我只需要一個單獨的連接來執行我的查詢。 ActiveRecord可以提供這個嗎?我已經看到連接到多個數據庫的討論,但沒有多個連接到同一個數據庫。

如果有更好的方法,解決方案不必涉及ActiveRecord。

我們的Rails和ActiveRecord版本是3.2.3。

回答

16

數據庫連接在每個線程的基礎上完成(這基本上是需要線程安全的),你可以使用你的優勢:只是在一個單獨的線程中執行代碼,例如

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

由於軌道4,activerecord不再收回以這種方式自動創建的連接。爲了避免連接泄漏,您需要將它們返回到池中。正如馬特·康奈利指出,要做到這一點最簡單的方法是使用with_connection方法,將回檢查連接在塊的結尾,例如

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

我認爲你更好地理解這個問題:) – PriteshJ 2012-07-26 18:39:34

+1

確保你完成後返回到連接池的連接! – 2014-08-11 00:48:38

+0

好電話! - 答案已過時。 – 2014-08-11 12:52:46

1

DDL和一些更多的查詢火災隱式提交,使他們不能被回滾按mysql的文檔

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

這些隱含結束任何交易活躍於當前會話,因爲如果你做了一個COMMIT在執行該語句之前。

如果兩者之間沒有這樣的查詢,那麼您可以使用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瞭解更多詳情。

+0

筆者在談論將始終隱式提交事務語句(如改變表) – 2012-07-26 18:23:57

+0

@FrederickCheung,從問題「的ActiveRecord :: Base.connection.execute觸發了暗示提交這是一個問題。「讓我相信他希望自己明確地控制交易。糾正我,如果我錯了 – PriteshJ 2012-07-26 18:26:48

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 
相關問題