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, запись заблокирована, и когда она будет выпущена, другие выбирают, не найдут запись.