为什么这个查询导致死锁?
问题描述:
我用这个查询并发工人之间分配行:为什么这个查询导致死锁?
SET @update_id := 0;
UPDATE tablename
SET processed = -1, id = (SELECT @update_id := id)
WHERE processed = 0
LIMIT 1
SELECT @update_id as id;
有时它扔了僵局例外,我刚刚重新启动它。但是,如果工人人数足够多,几乎每次都会陷入僵局,并陷入重试循环。如何正确地重写它?
答
你应该有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;
你肯定这应该正常工作?如果在select子查询返回之后但在更新发生之前修改了行?我应该检查返回值并重新启动查询如果0行被修改? – Poma
'AND processed = 0'应该阻止它。 是的,如果0行被修改或返回0,你应该重新启动查询。您可能需要增加检查有任何一行'处理= 0',所以你不必无限循环。 另一种方法是设置的ProcessID,而不是-1,那么它可能会简化事情,你要处理的崩溃进程的任何情况。 '更新TN组加工=其中加工= 0极限1;从TN 选择id其中加工= '' –
常规错误:1093您不能指定目标表“表名”的更新在FROM clause' – Poma