Предположим, у нас есть две таблицы в базе данных: products и orders. При оформлении заказа необходимо сделать два запроса — добавить новую запись в таблицу orders и уменьшить количество доступных товаров в таблице products. Если происходит ошибка при изменении одной из таблиц, то данные в базе могут оказаться несогласованными. Чтобы избежать таких ситуаций, используются транзакции.
Транзакции - это механизм обеспечения целостности данных в базе данных, который позволяет выполнить несколько операций как единое целое. Если одна из операций в транзакции завершается неудачно, то все предыдущие операции в транзакции откатываются, возвращая базу данных в исходное состояние
При создании соединения PDO по умолчанию работает в режиме автоматической фиксации. Это значит, что каждый запрос к базе данных, который вы выполняете, неявно заключается в транзакцию. Чтобы явно указать начало транзакции, нужно использовать метод beginTransaction()
. Если все запросы в рамках транзакции выполнены успешно, вы можете зафиксировать её методом commit()
. Если же во время выполнения одного из запросов произошла ошибка, транзакция откатывается методом rollBack()
и база данных остается без изменений
$conn = new PDO('sqlite::memory:');
try {
// Начало транзакции
$conn->beginTransaction();
// Выполняем запросы в рамках транзакции
$conn->exec("INSERT INTO users (id, username, phone) VALUES (12, 'Joe', '1234')");
$conn->exec("INSERT INTO salary (id, user_id, amount) VALUES (8, 12, 50000)");
// Фиксируем результат, если все запросы в рамках транзакции выполнились успешно
$conn->commit();
} catch (Exception $e) {
// Откатываем изменения, если что-то пошло не так
$conn->rollBack();
echo "Ошибка: {$e->getMessage()}";
}
В рамках транзакции можно выполнять любое количество запросов
Самостоятельная работа
- Выполните шаги из урока у себя на компьютере
Проверьте работу транзакций на практике. Напишите несколько запросов в рамках транзакции. Сымитируйте ошибку во время выполнения одного из запросов. Для этого можно перед фиксацией транзакции методом
commit()
выбросить ошибку:throw new Exception("Ошибка во время транзакции");
Сделайте выборку из базы данных и убедитесь, что база данных осталась без изменений
Дополнительные материалы
![Аватары экспертов Хекслета](https://cdn2.hexlet.io/assets/faces/mentors-756ab67c814cd4c22715666812a66c9dac9ac2d20176a10b0e932ee851a918e0.png)
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты
- Статья «Как учиться и справляться с негативными мыслями»
- Статья «Ловушки обучения»
- Статья «Сложные простые задачи по программированию»
- Вебинар «Как самостоятельно учиться»
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.