2011-04-03 89 views
1

我的問題很簡單,但我在rails上有點新的ruby(和網絡編程),並且找不到一個好答案。我如何確保在Heroku上以原子方式發生兩個(或更多)數據庫事務?Heroku上的多個數據庫事務的原子性問題

我可以使用互斥鎖對應用程序進行編碼,就像我使用任何多線程應用程序一樣,希望它能夠在分佈式服務器環境(如Heroku)中正常工作?如果不是,確保兩個或多個數據庫事務的原子性的最佳方法是什麼?

我知道Heroku使用PostgreSQL,它可以讓我獲得一個數據庫鎖的數組,但這些鎖只能持續一個事務。此外,我熟悉互斥鎖(和pthreads)來同步多線程應用程序,但我不確定這些約定是否可以在Heroku上按預期工作,特別是如果我的實際應用程序代碼在多個服務器上運行。

編輯

我絕對應該解釋我想要做的更多一點。我需要對數據庫進行兩次調用。第一次調用是讀取布爾值。如果這個布爾值是真的,我需要做一些動作,如果它是假的,我需要做別的。如果我讀了TRUE,那麼我需要做一些其他的東西(與外部API接口等),如果成功,那麼我需要將布爾值設置爲false。問題是我不知道如何避免多個客戶端從數據庫中讀取真實的情況,實際上,當一個客戶端正在寫入虛假路由但尚未完成之前我需要做的其他事情時寫作虛假。

+0

這將有助於知道爲什麼你需要2個單獨的交易。什麼阻止您將更多操作放入單個事務中? – 2011-04-03 04:29:25

回答

0

這裏有一個替代方案,可能工作:

修改您的布爾字段,允許存儲三態變量。 (日期/時間可能是好的太多,我會有點解釋。)

那麼像這樣的代碼操作:

begin transaction 
    read flag 
    if true 
     set flag to "processing" state 
    if false 
     perform other activity 
commit 

如果該標誌是true,那麼現在將設置爲processing ;調用外部API,幹什麼就幹什麼,而當結果出來:

begin transaction 
    read flag 
    if "processing" 
     set flag to false 
    if true 
     warn loudly 
    if false 
     warn loudly 
commit 

當然,如果工藝處理外部API死亡或時間過長塊,你會想知道,並能恢復。這就是爲什麼將日期/時間存儲到標誌中是很好的 - 如果它已經處於processing狀態六分鐘,然後殺死它並重新啓動。

使用posix信號燈或類似工具會有些不錯,但我希望您的Rails後端進程可以在不同的機器上每分鐘執行一次。

+0

有趣。我一定會試試這個。如果兩個進程設法到達API階段並且在第二個代碼塊中連續讀取「處理」標誌狀態,似乎仍然存在「競爭條件」。但是,發生這種情況的可能性非常低(我認爲)。 – kikster 2011-04-03 18:00:31