Выполнение нескольких запросов с помощью mysqli_multi_query и транзакций - PullRequest
3 голосов
/ 25 августа 2011

Я разрабатываю систему обновления для веб-приложения, написанного на PHP. В процессе обновления мне может понадобиться выполнить несколько сценариев MySQL.

Основной процесс запуска сценариев:

  1. Поиск сценариев Mysql
  2. Начать транзакцию
  3. Выполнить каждый скрипт с mysqli_multi_query, так как скрипт может содержать несколько запросов
  4. Если все идет хорошо, ВЫПОЛНИТЕ транзакцию, в противном случае ROLLBACK.

Мой код выглядит примерно так:

$link = mysqli_connect(...);

mysqli_autocommit($link, false);

// open dir and search for scripts in file.
// $file is an array with all the scripts
foreach ($scripts as $file) {

    $script = trim(file_get_contents($scriptname));

    if (mysqli_multi_query($link, $script)) {
        while (mysqli_next_result($link)) {
            if ($resSet = mysqli_store_result($link)) { mysqli_free_result($resSet); }

            if (mysqli_more_results($link)) { }
        }
    }

    // check for errors in any query of any script
    if (mysqli_error($link)) {
        mysqli_rollback($link);
        return;
    }
}
mysqli_commit($link);

Вот пример скриптов (для демонстрационных целей):

script.1.5.0.0.sql:
update `demo` set `alias` = 'test1' where `id` = 1;
update `users` set `alias` = 'user1' where `id` = 1;

script 1.5.1.0.sql: 
insert into `users`(id, key, username) values(3, '100', 'column key does not exist');
insert into `users`(id, key, username) values(3, '1', 'column key exists');

В этом случае сценарий 1.5.0.0 будет выполнен без ошибок, а сценарий 1.5.1.0 сгенерирует ошибку (например, для демонстрации предположим, что столбец key уникален и уже есть строка с key = 1 ).

В этом случае я хочу откатить каждый выполненный запрос. Но происходит следующее: первая вставка версии 1.5.1.0 отсутствует в базе данных (правильно), но обновления с версии 1.5.0.0 были выполнены успешно.

Примечания:

  1. Моим первым вариантом было разделить каждый запрос из каждого скрипта с помощью ";" и выполнять запросы самостоятельно. Это не вариант, так как я должен иметь возможность вставлять HTML-код в базу данных (например, если я хочу вставить что-то вроде "& nbsp;")
  2. Я уже искал StackOverflow и google и наткнулся на такие решения, как , это , но я бы предпочел использовать решение типа mysqli_multi_query, а не использовать функцию для разделения каждого запроса. Это более понятно и проще для целей отладки
  3. Я не проверял это, но я считаю, что мог бы объединить все сценарии и выполнить только запрос. Однако было бы полезно выполнять по одному сценарию за раз, чтобы я мог выяснить, какой сценарий содержит ошибку.
  4. Движок таблиц - InnoDB.

Благодарим вас, если вы можете указать какой-нибудь способ сделать эту работу.

Ответы [ 2 ]

2 голосов
/ 26 августа 2011

Редактировать: mysqli_multi_query() возвращает false только в случае сбоя запроса first . Если первый запрос не сработает, тогда ваш код будет работать mysql_store_result(), который в случае успеха оставит mysqli_error() пустым. Вам необходимо проверять наличие ошибок после каждой функции mysqli, которая может быть успешной или неудачной.

0 голосов
/ 05 мая 2014

Хорошо, потратив еще один день на отладку, я обнаружил проблему.

На самом деле, это не имеет ничего общего с самим кодом или функциями mysqli.Я привык к транзакциям MS SQL, которые поддерживают операторы DDL.MySQL не поддерживает операторы DDL и неявно фиксирует данные ( Неявная фиксация ).У меня была одна таблица DROP в одном из сценариев, которая автоматически передавала данные.

...