2009-11-12 100 views
1

我正試圖制定在我的應用程序中停止雙「預訂」的最佳方法。mySQL - 防止重複預訂

我有一個唯一的ID表,每個只能出售一次。

我目前的想法是使用一個事務來檢查選擇的產品是否可用,如果它們隨後插入一個'保留'的'狀態'列並插入'更新時間',那麼如果用戶繼續支付我更新狀態爲「已售出」。

每隔10分鐘,我對'status'='reserved'進行cron作業檢查,檢查超過10分鐘以前並刪除這些行。

有沒有更好的方法?我從來沒有使用過交易(我剛剛聽到過這個詞),所以如果有人能解釋我將如何做到這一點將是王牌。

回答

3

你試圖對你的「保留」狀態做什麼基本上是模擬交易行爲。讓專家(mysql)爲你處理它會更好。

請仔細閱讀關於database transactions,然後how to use them in MySQL。他們不是太複雜。隨後在這裏發佈有關它們的問題,我會盡力回覆。

編輯:現在,我想你的要求......也許只有使用數據庫事務是不是最好的解決方案 - 有噸交易開放的,等待用戶操作以提交交易可能不是一個良好的設計選擇。相反,使用「status」=「reserved」設計繼續你正在做的事情,但是使用數據庫中的事務來設置「status」的值,以確保該行不被兩個用戶同時「保留」 。

+0

我覺得這可能是這種情況,這就是爲什麼我問這個問題(而不是僅僅試圖去做)。所以我可以鎖定一行以便它不能被讀取 - 從而實現'保留'狀態。 – Mark 2009-11-12 17:04:20

+0

如果是這樣的話,可以鎖定多久?如果用戶剛剛關閉了網站,我該如何「解鎖」它? – Mark 2009-11-12 17:06:31

+0

事務可以配置爲超時,並且當它們超時時,鎖定的行將被釋放,並且任何更改都將回滾到其先前的狀態。 MySQL中的相關設置是innodb_lock_wait_timeout = 50(假設您使用innodb存儲引擎,很可能)。 – 2009-11-12 17:17:16

0

你不需要有任何添加狀態來做到這一點。

爲了避免dirty reads,您應該將數據庫設置爲isolation level這將避免它們。即REPEATABLE READ或SERIALIZABLE。

全球範圍內您可以set the isolation level,或會話特定。如果你所有的會話都需要隔離,那麼你可以在全局範圍內進行設置。

設置了隔離級別後,您只需使用在SELECT之前啓動的a transaction,並且可選擇更新狀態(如果SELECT顯示它尚未保留)。

4

儘管這裏有其他人建議,交易不是完整的解決方案。

聽起來你在這裏有一個web應用程序,選擇和購買預訂需要幾頁(步驟)。這意味着您將不得不在兩頁之間進行交易,這是不可能的。

你的方法(狀態欄)是正確的,但是,我會以不同的方式實施它。而不是狀態列,請添加兩列:reserved_byreserved_ts

  • 預留產品時,設置reserved_by給用戶或會話和reserved_tsnow()到的主鍵。
  • 當您尋找無保留的產品時,請查找reserved_ts爲零或超過10分鐘的產品。 (我實際上會比你告訴你的用戶的要早幾分鐘,以避免可能的競爭條件。)
  • 清除舊預留的cron作業變得不必要了。
+0

謝謝......這是明智的。我想我會保持地位,因爲我可以用它來保留,購買,禁用......以及許多其他可能的狀態。我已經創建了一個日期,所以我可以實現相同的方法。我也有一個用戶名。謝謝。 – Mark 2009-11-12 22:15:03

+0

我喜歡這種方法..清潔簡單.. – Winterain 2012-01-05 02:09:23