从 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
子句中为列添加索引,它可以直接转到该记录并将其锁定。没有其他记录被锁定,减少了死锁的可能性。
我有很多执行不同任务的控制台应用程序。我从 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
子句中为列添加索引,它可以直接转到该记录并将其锁定。没有其他记录被锁定,减少了死锁的可能性。