为什么此查询会导致死锁?

时间:2017-10-08 17:05:42

标签: mysql sql database

我使用此查询在并发工作程序之间分配行:

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

有时会抛出死锁异常,我刚刚重新启动它。但是,如果工作人员数量足够多,它几乎每次都会开始陷入僵局并陷入重试循环。如何正确地重写它?

1 个答案:

答案 0 :(得分: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;