Описание : в этой статье вы узнаете, как обрабатывать транзакции MySQL в PHP для обеспечения целостности данных базы данных.
Транзакция представляет собой совокупность взаимозависимых операторов SQL , которые необходимо выполнить во все или ничего режиме. Транзакция успешна, если все операторы SQL выполнены успешно. Сбой любого оператора приведет к откату системы до исходного состояния, чтобы избежать несогласованности данных.
Классическим примером транзакции является транзакция перевода денег с одного банковского счета на другой. Требуется три шага:
Если ошибка возникает на втором шаге, третий шаг не должен продолжаться. Кроме того, если ошибка возникает на третьем шаге, второй шаг должен быть отменен. Суммы обоих банковских счетов остаются нетронутыми в случае сбоя или корректно корректируются в случае успешного завершения транзакции.
Когда вы используете PDO для создания соединения с базой данных , поддерживающей транзакцию, устанавливается режим автоматической фиксации. Это означает, что каждый ваш запрос заключен в неявную транзакцию.
Обратите внимание, что не все механизмы хранения в MySQL поддерживают транзакцию, например, MyISAM не поддерживает транзакцию, однако InnoDB поддерживает.
Для обработки транзакции MySQL в PHP вы используете следующие шаги:
Мы создадим таблицу с именем accounts, чтобы продемонстрировать перевод денег между двумя банковскими счетами.
Сначала выполните следующую инструкцию для создания таблицы accounts:
CREATE TABLE accounts ( id INT AUTO_INCREMENT PRITanya KEY, name VARCHAR (50) NOT NULL, amount DECIMAL (19, 4) NOT NULL );
Во-вторых, вставьте две строки в таблицу accounts:
INSERT INTO accounts(name,amount) VALUES('AndreyEx',25000), ('Tanya',95000);
В-третьих, запрос к таблице accounts:
SELECT * FROM accounts;
Давайте посмотрим на следующий класс TransactionDemo:
<?php /** * PHP MySQL. Демонстрация транзакции */ class TransactionDemo { const DB_HOST = 'localhost'; const DB_NAME = 'classicmodels'; const DB_USER = 'root'; const DB_PASSWORD = ''; /** * Открыть подключение к базе данных */ public function __construct() { // открыть подключение к базе данных $conStr = sprintf("mysql:host=%s;dbname=%s", self::DB_HOST, self::DB_NAME); try { $this->pdo = new PDO($conStr, self::DB_USER, self::DB_PASSWORD); } catch (PDOException $e) { die($e->getMessage()); } } /** * PDO instance * @var PDO */ private $pdo = null; /** * Перевод денег между двумя счетами * @param int $from * @param int $to * @param float $amount * @возвращает true в случае успеха или false в случае неудачи. */ public function transfer($from, $to, $amount) { try { $this->pdo->beginTransaction(); // получить доступную сумму счета переводчика $sql = 'SELECT amount FROM accounts WHERE id=:from'; $stmt = $this->pdo->prepare($sql); $stmt->execute(array(":from" => $from)); $availableAmount = (int) $stmt->fetchColumn(); $stmt->closeCursor(); if ($availableAmount < $amount) { echo 'Недостаточная сумма для перевода'; return false; } // вычесть из передаваемого счет $sql_update_from = 'UPDATE accounts SET amount = amount - :amount WHERE id = :from'; $stmt = $this->pdo->prepare($sql_update_from); $stmt->execute(array(":from" => $from, ":amount" => $amount)); $stmt->closeCursor(); // добавить в учетную запись получателя $sql_update_to = 'UPDATE accounts SET amount = amount + :amount WHERE id = :to'; $stmt = $this->pdo->prepare($sql_update_to); $stmt->execute(array(":to" => $to, ":amount" => $amount)); // зафиксировать транзакцию $this->pdo->commit(); echo 'Сумма успешно переведена'; return true; } catch (PDOException $e) { $this->pdo->rollBack(); die($e->getMessage()); } } /** * закройте соединение с базой данных */ public function __destruct() { // close the database connection $this->pdo = null; } } // тестирование метода передачи $obj = new TransactionDemo(); // перевод 30000 со счета 1 на счет 2 $obj->transfer(1, 2, 30000); // перевод 5000 со счета 1 на счет 2 $obj->transfer(1, 2, 5000);
Мы открываем соединение с базой данных в методе __construct() и закрываем его в методе __destruct(). В методе transfer():
Давайте проверим метод transfer().
// перевод 30K со счета 1 на счет 2
$obj->transfer(1, 2, 30000);
Мы перевели 30K со счета AndreyEx на счет Tanya. Мы получили следующее сообщение:
Insufficient amount to transfer
Давайте сделаем еще один перевод:
// перевод 5К со счета 1 на счет 2
$obj->transfer(1, 2, 5000);
Скрипт возвращает следующее сообщение:
The amount has been transferred successfully.
Мы успешно перевели деньги между двумя банковскими счетами.
В этой статье мы шаг за шагом показали, как обрабатывать транзакции MySQL в PHP для обеспечения целостности данных.