Php 从MySQL表并发获取任务

Php 从MySQL表并发获取任务,php,mysql,transactions,deadlock,Php,Mysql,Transactions,Deadlock,我有很多执行不同任务的控制台应用程序。我正在从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 lock

我有很多执行不同任务的控制台应用程序。我正在从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);
有时我有重复的任务和“在尝试获取锁时发现死锁;尝试重新启动事务”。 我做错了什么


UPD:在“锁定”列上设置索引以解决问题

来自MySQL文档:

将精心选择的索引添加到表中。然后,查询需要扫描更少的索引记录,从而设置更少的锁

将索引添加到
locked
列可以解决此问题。如果没有它,
SELECT
查询必须扫描整个表,查找
locked=0
的行,并且必须锁定它单步执行的所有行


如果向
WHERE
子句中的列添加索引,它可以直接转到该记录并锁定它。没有其他记录被锁定,因此死锁的可能性降低。

来自MySQL文档:

将精心选择的索引添加到表中。然后,查询需要扫描更少的索引记录,从而设置更少的锁

将索引添加到
locked
列可以解决此问题。如果没有它,
SELECT
查询必须扫描整个表,查找
locked=0
的行,并且必须锁定它单步执行的所有行


如果向
WHERE
子句中的列添加索引,它可以直接转到该记录并锁定它。没有其他记录被锁定,因此死锁的可能性降低。

不认为这与错误有关,但当您指定
限制1
时,为什么要使用
while
循环?它不能返回多行,因此不需要循环。在
locked
列上是否有索引?尝试添加它。您的应用程序应根据处理此类错误,然后在出现错误时重新提交。设置一个索引,并保持事务的小规模可以最大限度地降低死锁风险。这段代码毫无意义!您设置运行事务,然后在每次更新后提交??您选择使用
LIMIT 1
,然后在单个结果上进行while循环??我在这里看到了数百个问题,人们使用
while
来处理查询结果,即使它只能返回一行,因为这是他们习惯的模式。新手程序员不会基于逻辑进行设计,他们只是复制他们以前看到或写过的东西而不去考虑。不要认为这与错误有关,但是当您指定
限制1
时,为什么要使用
while
循环?它不能返回多行,因此不需要循环。在
locked
列上是否有索引?尝试添加它。您的应用程序应根据处理此类错误,然后在出现错误时重新提交。设置一个索引,并保持事务的小规模可以最大限度地降低死锁风险。这段代码毫无意义!您设置运行事务,然后在每次更新后提交??您选择使用
LIMIT 1
,然后在单个结果上进行while循环??我在这里看到了数百个问题,人们使用
while
来处理查询结果,即使它只能返回一行,因为这是他们习惯的模式。新手程序员不会根据逻辑进行设计,他们只是复制他们以前看到或写过的东西而不去考虑。