W3docs

rollback

MySQLi — популярное расширение PHP для работы с MySQL. Функция rollback отменяет все изменения транзакции и восстанавливает состояние базы данных.

Введение

MySQLi — это расширение PHP для работы с базами данных MySQL. Функция mysqli_rollback() (или метод $mysqli->rollback() в объектно-ориентированном стиле) отменяет все изменения, сделанные с момента начала транзакции. На этой странице объясняется, когда и почему она нужна, как она соотносится с mysqli_commit(), а также приводятся рабочие примеры в процедурном и объектно-ориентированном стилях.

Если вы только начинаете работу с расширением, ознакомьтесь с PHP MySQLi и подключением к MySQL.

Что такое функция MySQLi Rollback?

Транзакция — это группа операций с базой данных, которые рассматриваются как единое целое: либо все они применяются, либо ни одна. mysqli_rollback() обеспечивает сценарий «ни одна» — она отбрасывает все изменения, сделанные с момента начала транзакции, и возвращает базу данных в предыдущее состояние.

Классический пример — перевод денег. Списание с одного счёта и зачисление на другой должны произойти вместе; если второй запрос завершается ошибкой, нельзя оставить первый применённым. Откат гарантирует, что баланс останется верным.

bool mysqli_rollback(mysqli $mysql, int $flags = 0, ?string $name = null)

Функция возвращает true при успехе и false при ошибке. Необязательный параметр $name позволяет откатиться до именованной точки сохранения вместо всей транзакции.

Автофиксация: зачем вообще нужны транзакции

По умолчанию MySQL работает в режиме autocommit, то есть каждый отдельный оператор сразу и окончательно фиксируется — откатывать нечего. Вызов mysqli_begin_transaction() отключает автофиксацию на время транзакции, поэтому изменения остаются в ожидании, пока вы явно не вызовете commit() или rollback(). Подробнее о поведении читайте в разделе autocommit.

Как работает откат транзакции

Полная транзакция состоит из четырёх шагов:

  1. Подключение к серверу.
  2. Начало транзакции с помощью mysqli_begin_transaction().
  3. Выполнение запросов.
  4. Фиксация при успехе всех операций или откат при возникновении ошибки.

Вот полный пример в процедурном стиле:

<?php
// Create a connection to the MySQL server
$conn = mysqli_connect("localhost", "username", "password", "database");

// Check connection
if (!$conn) {
    die("Connection failed: " . mysqli_connect_error());
}

// Start a transaction
mysqli_begin_transaction($conn);

// Execute queries and make changes to the database
$insert = mysqli_query($conn, "INSERT INTO `my_table` (column1, column2) VALUES ('value1', 'value2')");
$update = mysqli_query($conn, "UPDATE `my_table` SET column1 = 'new_value' WHERE id = 1");

// Check if queries succeeded
if ($insert && $update) {
    // Commit the transaction if all queries succeed
    mysqli_commit($conn);
    echo "Transaction committed successfully.";
} else {
    // Rollback the changes if any query fails
    mysqli_rollback($conn);
    echo "Transaction failed and rolled back: " . mysqli_error($conn);
}

mysqli_close($conn);
?>

Транзакция запускается, выполняются два запроса, и результат определяет исход: фиксация при успехе, откат при ошибке. Обратите внимание, что mysqli_query() возвращает false только при ошибке SQL-уровня — исключения не выбрасываются, поэтому нужно самостоятельно проверять возвращаемое значение, если только не включить режим исключений (показано ниже).

Объектно-ориентированный стиль с подготовленными выражениями

Большинство промышленного кода использует объектно-ориентированный API совместно с подготовленными выражениями, которые предотвращают SQL-инъекции, разделяя запрос и данные. Включение режима выброса исключений позволяет обернуть всю транзакцию в один блок try/catch и выполнять откат из одного места:

<?php
// Throw exceptions on any MySQLi error instead of returning false
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);

$mysqli = new mysqli("localhost", "username", "password", "database");

$mysqli->begin_transaction();

try {
    $stmt = $mysqli->prepare("UPDATE accounts SET balance = balance - ? WHERE id = ?");
    $stmt->bind_param("di", $amount, $fromId);
    $amount = 100.00;
    $fromId = 1;
    $stmt->execute();

    $stmt = $mysqli->prepare("UPDATE accounts SET balance = balance + ? WHERE id = ?");
    $stmt->bind_param("di", $amount, $toId);
    $toId = 2;
    $stmt->execute();

    // Both updates succeeded — make them permanent
    $mysqli->commit();
    echo "Transfer committed.";
} catch (mysqli_sql_exception $e) {
    // Anything threw — undo everything
    $mysqli->rollback();
    echo "Transfer failed and rolled back: " . $e->getMessage();
}

$mysqli->close();
?>

Поскольку MYSQLI_REPORT_STRICT заставляет неудавшиеся операторы выбрасывать mysqli_sql_exception, не нужно проверять возвращаемое значение каждого запроса — блок catch обрабатывает все пути ошибок. Подробнее о try/catch читайте в разделе PHP exceptions.

Откат до точки сохранения

Точка сохранения — это именованный маркер внутри транзакции. Откат до неё отменяет только работу, выполненную после точки сохранения, оставляя более ранние изменения в ожидании. Это удобно, когда часть транзакции является необязательной:

<?php
$mysqli->begin_transaction();

$mysqli->query("INSERT INTO orders (customer_id) VALUES (5)");
$mysqli->savepoint("after_order");

$mysqli->query("INSERT INTO order_items (order_id, sku) VALUES (LAST_INSERT_ID(), 'BAD')");

// Undo only the order_items insert; the order row remains pending
$mysqli->rollback(0, "after_order");

$mysqli->commit(); // commits the order without the bad item
?>

Случаи использования функции MySQLi Rollback

Функция MySQLi Rollback полезна в различных сценариях, в том числе:

1. Целостность данных

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

2. Обработка ошибок

Обеспечивает чистый механизм восстановления. При возникновении сбоя откат предотвращает появление «осиротевших» или повреждённых данных, позволяя приложению записывать и отображать понятные сообщения об ошибках.

3. Управление транзакциями

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

Преимущества функции MySQLi Rollback

Функция MySQLi Rollback предлагает разработчикам на PHP несколько технических преимуществ:

1. Атомарность

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

2. Упрощённая отладка

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

3. Оптимизация производительности

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

Частые подводные камни

  • Важен движок хранилища. Откат поддерживают только транзакционные движки. Стандартный InnoDB MySQL поддерживает его, тогда как более старый движок MyISAM молча игнорирует транзакции, то есть откат там ничего не меняет. Убедитесь, что ваши таблицы используют InnoDB.
  • DDL-операторы автоматически фиксируются. Такие операторы, как CREATE TABLE, ALTER TABLE и DROP TABLE, в MySQL неявно фиксируют текущую транзакцию — их нельзя откатить. Держите изменения схемы за пределами транзакций, которые вы планируете отменять.
  • Откат выполняется ровно один раз. После commit() или полного rollback() транзакция завершена. Перед выполнением новой транзакционной работы нужно начать новую транзакцию.
  • Разрыв соединения автоматически откатывает транзакцию. Если соединение теряется в середине транзакции, MySQL автоматически выполняет откат — незафиксированная работа никогда не остаётся в частично применённом состоянии.

Заключение

Функция mysqli_rollback() необходима разработчикам на PHP, которым нужно отменять изменения базы данных в ходе транзакции. Она обеспечивает целостность данных, упрощает управление транзакциями и улучшает обработку ошибок. Следуя шагам, описанным в этом руководстве, разработчики могут безопасно реализовать откаты для поддержания надёжной работы с базой данных.

Практика

Практика
Какова цель функции rollback() в PHP?
Какова цель функции rollback() в PHP?
Was this page helpful?