2015-12-23 284 views
0

我有一個設計問題。考慮在多個集羣環境中運行的應用程序,可以說有3個集羣。應用程序偵聽目錄,並處理所有導出的新文件並將其發送到文檔管理系統。我只想要一個集羣處理給定的文件,這樣我就可以避免競爭條件。爲此,我創建了一個名爲DocumentLock的鎖表,以便我可以使用數據庫作爲仲裁者。這3列是guid(主鍵),文件ID(這是來自文件的唯一名稱),鎖定時間戳。我正在使用Spring事務,並將Oracle作爲數據庫。我打算使用Read_Committed隔離級別。春季交易和插入數據庫

因此,假設集羣A獲取文件A,同時集羣B也獲得文件A的保存。現在,使用事務A的集羣A將嘗試插入到DocumentLock表中,並且可以說它是成功的。所以我將在DocumentLock表中有1行,唯一的ID是文件A(文件名)。現在,同時使用Tx-B的集羣B嘗試向DocumentLock表中插入一條記錄,但由於我使用'Read_Committed'隔離級別,因此需要等到Tx-A提交。因此TX-B將等待州。一旦Tx-A被提交,現在Tx-B將嘗試插入相同的記錄(文件A),並且因爲它違反了唯一性約束,它將引發錯誤。

我對Read_committed的理解是否正確?

我試圖避免多個集羣在表中插入相同的文件(唯一記錄),所以我假設如果兩個事務開始同時插入相同的文件名,其中一個需要等到另一個一個是承諾?那麼Oracle如何決定哪個事務(Tx-A或Tx-B)獲得表(鎖)?還有Read_committed,整個表是鎖定的,還是隻是行?

另外,如果不同的文件集B中獲取的舉行,說文件B應該插入沒有任何問題的DocumentLock,爲羣集A是處理文件A和集羣B需要處理的文件B. 感謝您的幫助

回答

1

我正在提供替代方法來解決這個問題。

將隔離級別設置爲READ UNCOMMITTED。這將確保任何未提交的數據庫更新也可以由其他事務準備好。這種方法的好處是,從一個羣集插入數據庫的任何內容都可以立即被所有其他羣集訪問。通過這種方式,人們可以通過一些應用程序邏輯來確定誰應該獲得鎖定。

讓我們來看看案例。

案例1:羣集A和B都試圖在文件f獲得鎖

  • 集羣A想冒頭文件的F.

  • 集A在搜索數據庫,看看是否有一個已經得到了鎖定。

  • 集羣A收到文件F的保持和記錄插入到表中, 但它並沒有犯

  • 集B要採取文件的第F.

  • 集B的交易在數據庫中進行搜索並查找由羣集A
    插入的條目,即使未提交該條目也是如此。

案例2:羣集A和B都試圖讓文件F1和F2

  • 集羣A要採取文件F1的保持鎖。
  • 集羣A在數據庫中搜索,看看是否有人已經獲得鎖定。
  • 集羣A獲取文件F1並將記錄插入表 但它沒有提交事務
  • 集羣B想抓住文件F2。
  • 集羣B在數據庫中搜索,看看是否有人已經獲得鎖定。
  • 集羣B獲取文件F2並將記錄插入表 但它沒有提交事務。
  • 集羣A和集羣B提交事務。

我不確定插入File f記錄是否沒有被集羣A提交,在這種情況下,如果集羣B也插入文件f的記錄,數據庫將拋出唯一性錯誤。所以這個解決方法來檢查應用程序邏輯中的所有內容可以提供幫助。

+0

感謝您的回答。對於案例1,如果由於某種原因事務A被回滾,並且集羣B認爲集羣A處理了文件F1。這不是髒讀的經典案例嗎? –

+0

如果你正在做一些處理這些文件的事情。您的羣集邏輯應該再次遍歷文件列表以確定是否有任何文件需要處理。在上面提到的Dirty Read的情況下,集羣B在再次嘗試循環文件時應該得到文件F.應該有一些連續的輪詢方法來查找未處理的文件。這種方式會在下次輪詢中處理髒讀。 –

+0

這是有道理的。謝謝 –