У меня есть несколько вопросов о том, как работает этот код из руководства по PHP. Я вижу другие примеры, которые генерируют исключения (обычно объектно-ориентированный код) или используют флаги для отслеживания сбоев каждого отдельного запроса.
Мой вопрос заключается в том, почему вы должны отмечать ошибки и проверять наличие флага, прежде чем принять решение о коммите или откате. Из приведенного ниже примера видно, что если фиксация не работает, ни один из запросов все равно не будет зафиксирован.
Я также заметил, что они просто выходят при неудаче коммита. Это автоматически откатывает все?
<?php
$link = mysqli_connect("localhost", "my_user", "my_password", "test");
/* check connection */
if (!$link) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}
/* set autocommit to off */
mysqli_autocommit($link, FALSE);
mysqli_query($link, "CREATE TABLE Language LIKE CountryLanguage");
/* Insert some values */
mysqli_query($link, "INSERT INTO Language VALUES ('DEU', 'Bavarian', 'F', 11.2)");
mysqli_query($link, "INSERT INTO Language VALUES ('DEU', 'Swabian', 'F', 9.4)");
/* commit transaction */
if (!mysqli_commit($link)) {
print("Transaction commit failed\n");
exit();
}
/* close connection */
mysqli_close($link);
?>
Из приведенного ниже примера видно, что если фиксация не работает, ни один из запросов все равно не будет зафиксирован.
Правильно.
Но дело в том, что ошибка может произойти не только с коммитом. Но — еще более вероятно — с одним из выполненных запросов. Таким образом, вам нужно проверить не только результат фиксации, но также результат каждого запроса и прервать всю операцию.
Итак, ваш вопрос должен читаться как
Отказ mysqli автоматически откат?
И ответ «да и нет».
По умолчанию это не так.
Но если вам удастся прервать выполнение сценария в случае сбоя запроса, ссылка будет закрыта и транзакция будет автоматически откатана. Приведенный ниже код преобразует ошибки mysql в фатальные ошибки PHP, которые автоматически выполнят откат в случае сбоя одного из запросов.
<?php
/* set the proper error reporting mode */
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$link = mysqli_connect("localhost", "my_user", "my_password", "test");
/* set autocommit to off */
mysqli_autocommit($link, FALSE);
/* Run your queries */
mysqli_query($link, "CREATE TABLE Language LIKE CountryLanguage");
mysqli_query($link, "INSERT INTO Language VALUES ('DEU', 'Bavarian', 'F', 11.2)");
mysqli_query($link, "INSERT INTO Language VALUES ('DEU', 'Swabian', 'F', 9.4)");
/* commit transaction */
mysqli_commit($link);
/* this is the last line, NO other code is needed */
Других решений пока нет …