2012-08-25 43 views
1

我有一個程序任務來執行表的一致性更新。爲了簡單起見,我將討論虛擬表格來展示這個想法。所以我有兩個表格:usernoteMySQL - 通過兩個併發進程一致選擇和更新

noteid(主鍵自動增加)和user_id(外鍵),numbernext_number
number是一些用戶的說明。如果這是最新的用戶註釋或者可以等於下一個用戶註釋的數量(如C++鏈接列表中下一個節點的指針),則next_number可以等於0
因此,每個用戶的音符編號從1到n。

現在有的兩個過程(過程Proc1 PROC2 )有需要將行插入到表note爲相同的用戶。

所以每個該處理開始交易,獲取最新的用戶注意到的number,然後執行一些其他動作與number遞增到1

插入新行是否有可能,這兩個進程(過程Proc1PROC2)將取回他們的交易中相同number(說第一個進程將執行SELECT語句之前第二個進程將執行其INSERTUPDATE語句)?

例如:

  1. 過程Proc1:SELECT number FROM note WHERE user_id = 1 AND next_number = 0 - 檢索數
  2. PROC2:SELECT number FROM note WHERE user_id = 1 AND next_number = 0 - 檢索數
  3. 過程Proc1:INSERT INTO note SET number = 6, next_number = 0, user_id = 1, text = 'Proc1 note'
  4. PROC2:INSERT INTO note SET number = 6, next_number = 0, user_id = 1, text = 'Proc2 note'
  5. 過程Proc1 :UPDATE note SET next_number = 6 WHERE number = 5
  6. PROC2:UPDATE note SET next_number = 6 WHERE number = 5
  7. 過程Proc1:commiting的過程Proc1交易
  8. PROC2:commiting PROC2

如果有可能的交易,如何避免這種情況? SELECT ... FOR UPDATE會解決這個問題嗎?

更新 - 簡化我的問題

所以一般的問題是,如果進程啓動的事務如何禁止其他MySQL會話與當前交易正與該行的互動?

+0

這是一個好主意,使'筆記'列也自動增量。然後使用update未設置next_number =(select last_insert_id())where next_number = 0;當然,需要在交易中完成整個事情。 –

+0

自動增量確保生成值的唯一性,但不是正確的順序。沒有任何保證它會產生一個「1,2,3」序列而不是「1,3,4」。同樣在我的情況下,'note'表格包含不同用戶的註釋。所以自動增量在這裏不是一種方法。 –

回答

0

你應該測試這個以確保它正在做正確的事情,但第二個SELECT ... LOCK IN SHARE MODE語句應該阻塞,直到第一個完成。您還應該查看SERIALIZABLE事務隔離級別,它隱式設置它。

+0

感謝您的回答,[約書亞](http://stackoverflow.com/users/211760/)。你能否更好地解釋你的答案,尤其是考慮到我的** UPDATE **中的問題? 另外我不得不說,在我的應用程序中,您提到的測試可能有點困難,所以最好知道在這種情況下哪種方法是正確的。 –

+0

無論哪個事務首先執行'... LOCK IN SHARE MODE'應持有這些行,直到事務完成。爲了測試這個,我會打開兩個連接到服務器。開始第一個事務,然後嘗試運行第二個事務。它應該阻塞,直到第一個完成。 –

+0

我明白了。謝謝。似乎我需要編寫一些多線程Java應用程序,它將使用「SELECT ... LOCK IN SHARE MODE」並行地運行非同步線程事務。我會通知您有關結果,如果運行良好,我會接受答案。 –