2014-11-04 29 views
0

說我有連接到另一個數據庫模型:與ActiveRecord的分佈式事務邊界

class Model1 < ActiveRecord::Base 
    establish_connection {config_to_connection_to_database2} 
end 


class Model2 < ActiveRecord::Base 
    establish_connection {config_to_connection_to_database2} 
end 

當我開始一個事務,說

Model1.transaction do 
    Model1.create! something 
    Model2.create! something 
    #some other thing 
end 

生成的SQL是:

BEGIN 
    INSERT INTO model1 ... 
    BEGIN 
    INSERT INTO model2 ... 
    COMMIT 
#some other thing might happen here 
COMMIT 

#some other thing發生錯誤時,INSERT INTO model2將不會滾動因爲它在一個嵌套事務中並且已經提交,因此回滾了INSERT INTO model1

我發現了一個醜陋的解決方法:

Model1.transaction do 
    Model2.transaction do 
    Model1.create! something 
    Model2.create! something 
    #some other thing 
    end 
end 

的SQL變爲:

BEGIN 
    BEGIN 
    INSERT INTO model1 ... 
    INSERT INTO model2 ... 
    #some other thing might happen here 
    COMMIT 
COMMIT 

它的工作原理,但有點討厭我。

所以我的問題是:怎樣的ActiveRecord決定是否應該換一個SQL語句BEGINCOMMIT(貌似ActiveRecord的不會刻意去檢查,如果模型1和模型2被連接到同一個數據庫),並有一個更好的解決方法在這裏?

回答

0

原來的解決方案是非常簡單的(答案是正確的的ActiveRecord :: Base的文件中,我是完全失明)

成立專班

class Database2 < ActiveRecord::Base 
    self.abstract_class = true #this is important, otherwise the inherited class's table name would be 'database2' 
    establish_connection your_connection_config 
end 

然後Model1Model2剛需要繼承Database2,並且一切正常。

萬一有人奇怪,這樣Model1Model2共享相同的連接池。如果你在每個類中調用establish_connection,那麼每個類都有自己的連接池,這會浪費資源,並且會在我的問題中提到事務問題。