Удаление файлов и строк из результирующего набора MySQL

#php #mysql

#php #mysql

Вопрос:

У меня есть окно Linux, которое собирает данные, создает файлы и хранит данные о файлах в таблице MySQL. Мне нужно иметь возможность начать выборочную обрезку этих данных.

Я планировал использовать скрипт php-cli и запускать его каждую ночь через cron.

Основная предпосылка заключается в выборе строк, которые соответствуют критериям удаления, удалении файлов из соответствующих строк, затем удалении строк. Путь / имя файла сохраняются в строке.

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

 SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
START TRANSACTION;
SELECT foo FROM bar WHERE wee = 'yahoo!';
DELETE FROM bar WHERE wee = 'yahoo!';
COMMIT;
  

Я знаю, как я могу удалить файлы, используя функцию php unlink(). Я просто не уверен, как сохранить результирующий набор, выполнить итерацию по удалению файлов, затем удалить строки результирующего набора из таблицы… без большого уродливого взлома с записью во временный текстовый файл или что-то в этом роде.

Будем признательны за любую помощь. Спасибо!

РЕДАКТИРОВАТЬ: PHP 5.3.6, MySQL 5.0.77

Комментарии:

1. Ehm. Я действительно не вижу проблем. Транзакция гарантирует, что она ВЫБЕРЕТ, а затем удалит эту строку, и unlink(); функция действительно работает. В чем ваша проблема?

Ответ №1:

Я не думаю, что вам нужна транзакция, если вы просто запускаете 1 запрос на УДАЛЕНИЕ.

 <?php

    $pdo::prepare("SELECT [...]");
    foreach($result as $pathname) {
      unlink($pathname);
      if (/*everything went good*/)
        $pdo::prepare("DELETE [...]");
    }


?>
  

Ответ №2:

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

Итак, просто запросите (в одном запросе, если возможно) все записи, которые подлежат удалению. На каждой итерации удаляйте файл и эту запись.

Единственная «проблема» заключается в том, что файловая система обрабатывается не в той же транзакции, что и оператор SQL, поэтому, если при удалении записи возникает ошибка, файл все равно может быть удален и наоборот.

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