SELECT, затем сразу DELETE запись mysql

У меня есть PHP script, который запускает запрос SELECT и сразу же удаляет запись. Существует несколько машин, которые пингоруют один и тот же файл php и извлекают данные из одной таблицы. Каждый удаленный компьютер работает на задании cron.

Моя проблема в том, что иногда она не может удаляться достаточно быстро, поскольку некоторые из компьютеров пинговали в одно и то же время.

Мой вопрос в том, как я могу выбрать запись из базы данных и удалить ее до того, как следующий компьютер ее захватит. Сейчас я просто добавил небольшую задержку, но она не очень хорошо работает. Я попытался использовать транзакцию, но я не думаю, что она применима здесь.

Вот пример фрагмента моего script:

<?php

$query = "SELECT * FROM `queue` LIMIT 1";
$result = mysql_query($query) or die(mysql_error());

while($row = mysql_fetch_array($result)){
    $email = $row['email'];
    $campaign_id = $row['campaign'];
}

$queryx = "DELETE FROM `queue` WHERE `email` = '".$email."'";
$resultx = mysql_query($queryx) or die(mysql_error());

?>

Действительно оцените помощь.

Ответ 1

Поместите свои запросы на удаление внутри цикла while, просто вы можете увеличить лимит из своего выбора.

<?php
$query = mysql_query("SELECT * FROM `queue` LIMIT 1") or die(mysql_error());

while($row = mysql_fetch_array($query)){
    mysql_query("DELETE FROM `queue` WHERE `email` = '" . $row['email'] . "' LIMIT 1") or die(mysql_error());
}
?>

Приведенный выше код будет таким же, как и при запуске:

mysql_query("DELETE FROM `queue` LIMIT 1") or die(mysql_error());

Будьте осторожны с использованием вашего запроса на удаление, если поле электронной почты пустое, оно удалит все строки, у которых есть пустое электронное письмо. Добавьте LIMIT 1 к вашему запросу удаления, чтобы избежать удаления нескольких строк.

Чтобы добавить случайную задержку, вы можете добавить sleep в начало script,

например:

<?php
$seconds = mt_rand(1,10);
sleep($seconds);
?>

Ответ 2

Я бы использовал столовые замки читайте больше здесь

Блокировка безопасна и применяется к одному сеансу клиента. Блокировка таблицы защищает только от неприемлемых чтений или записей другими сеансами.

Ответ 3

Если вы используете MariaDB 10:

DELETE FROM `queue` LIMIT 1 RETURNING *

Документация.

Ответ 4

Вы должны использовать подзапрос следующим образом:

<?php

$queryx = "DELETE FROM `queue` WHERE `email` IN (SELECT email FROM `queue` LIMIT 1)";
$resultx = mysql_query($queryx) or die(mysql_error());

?>

* Примечание. Всегда выбирайте только нужные поля... старайтесь избегать выбора *... это замедлит производительность.

Ответ 5

запустите запрос обновления, который изменит ключ, прежде чем вы сделаете выбор. Сделайте выбор по этому новому ключу, который известен только в том же сеансе.
Если таблица innoDB, запись заблокирована, и когда она будет выпущена, другие выбирают, не найдут запись.