2015-05-24 63 views
2

我目前使用的是Slick 3.x.x,它在對數據庫的所有調用中都是完全異步的。比方說,我有一張具有某種版本的表格。每次我從一個已經存在的條目創建一個新條目(即更新給定條目)時,我必須確保我增加了版本號。Scala異步數據庫調用

如何確保在數據庫通信的異步世界中可以保持數據完整性?在我的版本中,我會先選擇最大版本,這會讓我回到未來,然後使用這個Future的結果,遞增1併發出創建命令!

線程1可能很有可能是從select max版本開始並暫停了一段時間,迎合新請求的線程2可能會運行select for max版本並遞增並在數據庫中寫入新記錄。現在,thread1回來並嘗試執行相同的過程,但僅導致thread1會覆蓋thread2在數據庫中寫入的內容。

這可能是我可能最終有多個副本,因爲多個期貨可能運行的順序可能不同!

回答

3

應用程序管理其與數據庫交互的異步不會改變數據庫事務的語義。如果你想要原子的,一致的操作序列,那麼你想要一個數據庫事務。滑動offers稱爲transactionally的「組合器」,它將強制一系列操作在數據庫事務中運行。

+0

感謝您指向「事務性」的指針。在documentatin中,我可以看到有這樣一個警告:「警告: - 失敗不能保證在事務性包裝的單個DBIOAction級別上是原子級的,因此您不應該應用錯誤恢復組合器在這一點上,實際的數據庫事務是爲最外層的事務操作而創建和提交/回滾的。「我無法完全理解它。誰能解釋一下? – sparkr

+0

假設你有多個DBIOAction,可以稱它們爲'action1'和'action2'。你可以用'action1和Then action2'把它們串起來。假設你做了'(action1.transactionally和then action2).transactionally'嵌套事務語義不保證被支持,所以這可能等同於'(action1 andThen action2).transactionally'。所以像'(action1.transactionally.cleanUp(...)和Then action2).transactionally'這樣的構造可能會在回滾後無法清理。 '(action1和then action2).transactionally.cleanUp(...)'會抓住他們。 –

+0

說,我有(action1和then action2).transactionally產生一個表中的列的版本號2和另一個線程執行相同的方法,包含我的兩個行動會看到2或3或甚至1的版本號?由於(action1和then action2)的結果在事務上返回了Future,我怎樣才能保證另一個Future所看到的數據將是其之前Future的結果? – sparkr