ВЫБЕРИТЕ, затем немедленно УДАЛИТЕ запись MySQL - PullRequest
10 голосов
/ 04 февраля 2012

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

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

У меня вопрос, как я могу ВЫБРАТЬ запись из базы данных и удалить ее до того, как следующая машина получит ее? Сейчас я просто добавил небольшую задержку, но она работает не очень хорошо. Я пытался использовать транзакцию, но я не думаю, что она применима здесь.

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

<?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());

?>

Очень ценю помощь.

Ответы [ 5 ]

6 голосов
/ 04 февраля 2012

хорошо, я бы использовал блокировки таблиц подробнее здесь

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

4 голосов
/ 28 июня 2015

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

DELETE FROM `queue` LIMIT 1 RETURNING *

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

4 голосов
/ 04 февраля 2012

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

<?php

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

?>

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

1 голос
/ 04 февраля 2012

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

0 голосов
/ 04 февраля 2012

Поместите ваши запросы на удаление в цикл 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 в начало скрипта,

Например:

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