2017-10-08 86 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

相关问题