Я разрабатываю систему обновления для веб-приложения, написанного на PHP. В процессе обновления мне может потребоваться выполнить кучу скриптов MySQL.
Основной процесс запуска скриптов:
- Найдите скрипты Mysql
- Начать транзакцию
- Выполните каждый сценарий с mysqli_multi_query, поскольку сценарий может содержать несколько запросов.
- Если все в порядке, ЗАКОНЧИТЕ транзакцию, в противном случае - ОТКАТ.
Мой код выглядит примерно так:
$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 были выполнены успешно.
Примечания:
- Моим первым вариантом было разделить каждый запрос из каждого скрипта с помощью ";" и выполнять запросы независимо. Это не вариант, поскольку я должен иметь возможность вставлять HTML-код в базу данных (например, если я хочу вставить что-то вроде "& nbsp;")
- Я уже искал StackOverflow и google и наткнулся на такие решения, как this one, но я бы предпочел использовать такое решение, как mysqli_multi_query, а не использовать функцию для разделения каждого запроса. Это более понятно и проще для целей отладки
- Я не тестировал, но считаю, что смогу объединить все скрипты и выполнить просто запрос. Однако было бы полезно выполнять по одному сценарию за раз, чтобы я мог выяснить, в каком сценарии есть ошибка.
- Движок таблиц - InnoDB.
Благодарю, если вы можете указать какой-нибудь способ сделать эту работу.
2 ответа
Хорошо, потратив еще один день на отладку, я обнаружил проблему.
На самом деле это не имеет ничего общего ни с самим кодом, ни с функциями mysqli. Я привык к транзакциям MS SQL, которые поддерживают операторы DDL. MySQL не поддерживает операторы DDL и неявно фиксирует данные ( Неявная фиксация а>). У меня была одна таблица DROP в одном из скриптов, которая автоматически фиксировала данные.
Изменить: mysqli_multi_query()
возвращает false только в случае сбоя первого запроса. Если первый запрос не завершился ошибкой, ваш код запустит mysql_store_result()
, который в случае успеха оставит mysqli_error()
пустым. Вам необходимо проверять наличие ошибок после каждой функции mysqli, которая может быть успешной или неудачной.
Похожие вопросы
Связанные вопросы
Новые вопросы
php
PHP - это широко используемый высокоуровневый, динамический, объектно-ориентированный и интерпретируемый язык сценариев, в первую очередь предназначенный для серверной веб-разработки. Используется для вопросов о языке PHP.