从 MySQL table 并发获取任务

Concurrent getting tasks from MySQL table

我有很多执行不同任务的控制台应用程序。我从 php 脚本中获得独特的任务:

$mysqli->autocommit(FALSE);
$result = $mysqli->query("SELECT id, task FROM queue WHERE locked = 0 LIMIT 1 FOR UPDATE;");

while($row = $result->fetch_assoc()){ 
    $mysqli->query('UPDATE queue SET locked = 1 WHERE id="'.$row['id'].'";');
    $mysqli->commit();
    $response["response"]["task"] = $row["task"];
}

$mysqli->close();   
echo json_encode($response);

有时我有重复的任务,"Deadlock found when trying to get lock; try restarting transaction"。 我做错了什么?

UPD:在 "locked" 列上设置索引解决问题

来自 MySQL 文档 How to Minimize and Handle Deadlocks:

Add well-chosen indexes to your tables. Then your queries need to scan fewer index records and consequently set fewer locks.

locked 列添加索引应该可以解决此问题。没有它,SELECT 查询必须扫描 table,寻找带有 locked = 0 的行,并且必须锁定它经过的所有行。

如果在WHERE 子句中为列添加索引,它可以直接转到该记录并将其锁定。没有其他记录被锁定,减少了死锁的可能性。