2012-11-29 127 views
1

我有一個表tbl_orders。它有一個數量字段quantity。 在我的應用程序的某些部分,我需要通過1防止2個用戶同時更新相同的記錄

遞減量我已經知道了記錄的id(可從客戶端),所以我發出一個更新語句:

UPDATE tbl_orders 
SET quantity=quantity-1 
WHERE id= 6 

問題是這個查詢可能會意外地同時運行多次。 例如,2個客戶服務運營商可能會同時更新相同的記錄。 這意味着當它應該減少一次時,數量將減少2。

我試圖在事務中放置更新,但導致只會延遲第二個事務,直到提交第一個事務爲止。一旦提交,第二次更新就會運行並再次減少記錄。

如何確保在修改記錄時其他查詢失敗?

UPDATE:

的更新是有效的在客戶端的數量是在數據庫中的相同。例如,如果用戶在瀏覽器上看到數量5並想減少數量,則數據庫中的值必須相同。

更新2

我發現使用Doctrine 2樂觀鎖定一個很好的解釋here

+0

這可能不是在數據庫端解決的問題,因爲那時有時你會想* *量將由2。你需要告訴的萬無一失的方法,當多個查詢是一個意外,而當他們遞減'是故意的。 – histocrat

+0

你如何知道什麼時候允許更新通過以及何時不通過?例如,如果兩個用戶分別點擊按鈕毫秒,會發生什麼? –

+0

@ D-Rock如果客戶端的數量在數據庫中相同,則該值有效。例如,如果用戶在瀏覽器上看到數量5並想減少數量,則數據庫中的值必須相同。 – Songo

回答

5

一種方法我用/在過去是有一個時間戳列可見。查詢時,確保您在編輯記錄的開始時同時擁有ID和原始時間戳。然後,當你要更新,通過

update YourTable 
    set counter = counter -1, 
     TheTimestampColumn = new timestamp value 
    where ID = yourID 
    and TheTimeStampColumn = timeStampEditStartedWith 

發送這樣一來,誰與原來的開始時間戳會贏得第一個得到它。對於後面的那個,你必須跟蹤有多少條記錄被更新,如果這個數字等於零,那麼你會通知用戶另一個人在查看記錄時對記錄進行了更改。你想重新加載最新的數據? (或類似的東西)。

+1

嗯,這被稱爲樂觀鎖定,對吧? – Songo

+0

@Songo,取決於你是否樂觀:)但是,你預計沒有兩個人同時在記錄上工作,但並不強迫明確的LOCK延遲其他活動。更多的工作/跟蹤/反饋給用戶。 – DRapp

+0

@Songo Yep,作爲一個附註,使用'int'而不是'timestamp'是人們通常使用的另一種方式。 – Windle

相關問題