2017-08-07 114 views
0

我正在使用mariadb。有一個resource表,其中列idused標誌和其他資源描述符。每行表示一個資源分配單位。我在分配一行時遇到了麻煩。使用SQL分配資源(行)

在每一筆交易,我想:

  1. 選擇並鎖定行,是不是used
  2. used設置爲true
  3. 根據所選行操縱數據庫。
  4. 然後提交。

要求:

  • 可以有很多併發事務。
  • 它可以選擇任何不是used的行。
  • 它不應該阻止。
  • 如果步驟3失敗,事務將回滾並重新啓動。最好選擇不同的行。

首先我試過SELECT * FROM resource WHERE used=0 LIMIT 1 FOR UPDATE,但在同時發生的情況下,第二個事務會阻塞,直到第一個事務結束。

START TRANSACTION 
SELECT * FROM resource WHERE used=0 LIMIT 1 FOR UPDATE <-- second tx waits here until first commits 
... 
COMMIT 

然後我嘗試通過ORDER BY rand()添加隨機性。但似乎這將首先排序整個表,所以仍然阻塞。

START TRANSACTION 
SELECT * FROM resource WHERE used=0 ORDER BY rand() LIMIT 1 FOR UPDATE <-- still blocks 
... 
COMMIT 

任何提示?

+0

只是檢查,你使用什麼表格類型 – RiggsFolly

+0

@RiggsFolly我使用InnoDB – Xiao

+0

好吧,現在向我們展示一些你已經嘗試過的代碼。這將有助於解釋你正在嘗試做什麼 – RiggsFolly

回答

1

我假設你的處理將花費很少的時間,或者你有大量的併發事務 - 否則,接受阻塞可能更容易。

我已經解決了這個問題,因爲有一個更「粒狀」的「使用」。

在僞碼:

begin transaction 
select the row to process, set status to "in progress", and mark with unique process identifier 
end transaction 

begin transaction 
select the row with "in progress" and my unique process identifier 
complete other processing logic 
set row status to "used" 
if error: 
    rollback transaction 
    set flag to "error" 
else 
    commit transaction 

但這仍然阻塞表,但用於第二的一小部分。

我們有一個單獨的工作,尋找「被遺棄」的交易(帶有「錯誤」標誌的記錄,並將這些交易報告給管理控制檯)。

+0

感謝您的回答。但似乎並沒有清楚交易回滾時的「進行中」標誌。在進程ID管理和錯誤處理中可能需要更多的邏輯。 – Xiao

+0

我已經更新了答案 - 儘管這是高度特定於應用程序的。 –