【发布时间】:2017-01-04 15:42:48
【问题描述】:
我有很多执行不同任务的控制台应用程序。我从 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:在“锁定”列上设置索引解决问题
【问题讨论】:
-
不认为和错误有关,但是为什么在指定
LIMIT 1时使用while循环呢?它永远不能返回超过一行,所以你不需要循环。 -
locked列上有索引吗?尝试添加它。 -
您的应用程序应根据dev.mysql.com/doc/refman/5.7/en/innodb-deadlocks-handling.html处理此类错误,然后重新提交,以防出现错误。设置索引并保持较小的事务可以最大限度地降低死锁风险。
-
这段代码没有意义!您设置为运行事务,然后在每次更新后提交?你选择使用
LIMIT 1,然后while循环一个结果?? -
我在这里看到了数百个问题,人们使用
while来处理查询结果,即使它只能返回 1 行,仅仅是因为这是他们习惯的模式。新手程序员不根据逻辑进行设计,他们只是复制他们以前看到或写过的东西而不考虑它。
标签: php mysql transactions deadlock