2013-08-07 173 views
1

我對原子操作的理解是操作的步驟不應該與其他任何操作的步驟交錯 - 它應該作爲一個單元來執行。究竟是什麼意思春天交易是原子?

我有一個創建數據庫記錄的方法,首先檢查具有相同值的記錄是否已滿足某些其他參數,如果不存在,則創建該記錄。

在fakecode:

public class FooDao implements IFooDao { 

    @Transactional 
    public void createFoo(String fooValue) { 
     if (!fooExists(fooValue)) { 
      // DB call to create foo 
     } 
    } 

    @Transactional 
    public boolean fooExists(String fooValue) { 
     // DB call to check if foo exists 
    } 
} 

但是我所看到的,這是可能的是創造了兩個紀錄具有相同值,這表明這些行動已經以某種方式交錯。我知道,使用Spring的事務代理,對象內的方法的自我調用不會使用事務邏輯,但是如果從對象外部調用createFoo(),那麼我希望fooExists()仍然包含在同一個對象中交易。

我的期望是什麼事務性原子性應該強制執行錯誤?我是否需要使用同步塊來執行此操作?

回答

1

事務對數據庫的真正含義取決於隔離級別。關於Isolation (database systems)的wikipdia文章解釋得很好。

通常情況下,使用的隔離級別不是很高,例如:Read committed。這意味着可以從另一個事務中讀取數據,直到另一個事務被提交。 在你的情況下這還不夠,因爲這與你想要的相反。 - 所以明顯的解決方案是使用更嚴格和更慢的隔離級別:Repeatable reads


但說實話,我會用一個別的辦法:請有關列唯一的(但不刪除你的if (!fooExists(fooValue)) -check)。所以99%的檢查工作。在剩下的1%中,你會得到一個異常,因爲你試圖違反唯一約束。

+0

不幸的是,我不能在DB上使用唯一的約束,因爲它並不是絕對唯一的 - 正如前面提到的那樣還有其他參數,並且它們表示可以多次使用相同的值。 –

0

事務性意味着所有更新都發生在同一個事務中,即所有更新/插入/刪除成功或全部回滾(例如,如果您更新多個表)。

它並不保證事務內查詢的行爲,這取決於RDBMS及其配置(配置數據庫上的隔離級別)。

0

@Transactional默認情況下不會使代碼同步。兩個單獨的線程可以同時進入同一個塊,並導致插入發生。同步該方法並不是一個好的答案,因爲這會大大影響應用程序的性能。如果您的問題是由兩個不同的線程創建兩個相同的記錄,則可能需要在數據庫中添加一些具有唯一約束的索引,這樣重複的插入操作將失敗。

相關問題