2017-10-08 83 views
0

我用這個查詢併發工人之間分配行:爲什麼這個查詢導致死鎖?

SET @update_id := 0; 
UPDATE tablename 
    SET processed = -1, id = (SELECT @update_id := id) 
    WHERE processed = 0 
    LIMIT 1 
SELECT @update_id as id; 

有時它扔了僵局例外,我剛剛重新啓動它。但是,如果工人人數足夠多,幾乎每次都會陷入僵局,並陷入重試循環。如何正確地重寫它?

回答

0

你應該有processed列索引,並嘗試此查詢

SET @update_id := (SELECT id FROM tablename t WHERE processed = 0 LIMIT 1); 
SET @updated_id := 0; 
UPDATE tablename 
    SET processed = -1, id = (SELECT @updated_id := id) 
WHERE 
     id = @update_id 
     AND processed = 0; 

SELECT @updated_id as id; 

您可能需要直到你沒有零updated_id運行到這幾次。如果還沒有未處理的記錄,則需要處理這種情況。

替代做法:

假設每個進程具有獨特@process_Id和它僅處理一個記錄的時間和刪除或處理後設置處理,以-1。

UPDATE tablename SET processed = @process_id WHERE processed = 0 LIMIT 1;  
SELECT id FROM tablename t WHERE processed = @process_id; 
+0

你肯定這應該正常工作?如果在select子查詢返回之後但在更新發生之前修改了行?我應該檢查返回值並重新啓動查詢如果0行被修改? – Poma

+0

'AND processed = 0'應該阻止它。 是的,如果0行被修改或返回0,你應該重新啓動查詢。您可能需要增加檢查有任何一行'處理= 0',所以你不必無限循環。 另一種方法是設置的ProcessID,而不是-1,那麼它可能會簡化事情,你要處理的崩潰進程的任何情況。 '更新TN組加工= 其中加工= 0極限1;從TN 選擇id其中加工= '' –

+0

常規錯誤:1093您不能指定目標表「表名」的更新在FROM clause' – Poma

相關問題