私は、さまざまなタスクを実行する多くのコンソールアプリケーションを持っています。私は、PHPスクリプトからユニークなタスクを取得:MySQLテーブルからタスクを同時に取得する
$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のドキュメントHow to Minimize and Handle Deadlocksから問題
エラーとは関係ないと思いますが、なぜ 'LIMIT 1 'を指定するときに' while'ループを使用していますか?複数行を返すことはできないので、ループする必要はありません。 – Barmar
'locked'カラムにインデックスがありますか?それを追加してみてください。 – Barmar
アプリケーションは、このようなエラーをhttp://dev.mysql.com/doc/refman/5.7/en/innodb-deadlocks-handling.htmlに従って処理してから、エラーが発生した場合に再送信する必要があります。インデックスを設定し、トランザクションを小さく保つと、デッドロックのリスクを最小限に抑えることができます。 – user3606329