У меня много консольных приложений, которые выполняют разные задачи. Я получил уникальное задание из 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
оговорка, он может перейти непосредственно к этой записи и заблокировать ее. Другие записи не заблокированы, поэтому вероятность взаимоблокировки снижена.
Других решений пока нет …