Поддержка транзакций: BEGIN, COMMIT, ROLLBACK
Что такое транзакции и зачем они нужны? 🔄
Транзакция — это последовательность SQL-операций, которая либо выполняется целиком, либо не выполняется вообще. Представьте банковский перевод:
- Списали деньги с одного счёта → Зачислили на другой.
Если что-то пошло не так (например, отключили свет), транзакция гарантирует, что деньги не «исчезнут» где-то посередине.
Пример без транзакций:
UPDATE accounts SET balance = balance - 100 WHERE user_id = 1;
-- Ой, сервер упал здесь!
UPDATE accounts SET balance = balance + 100 WHERE user_id = 2;
Результат: у первого пользователя деньги списались, а второй их не получил. 💸
Три ключевые команды 🛠️
BEGIN— стартует транзакцию.COMMIT— подтверждает изменения (всё прошло успешно).ROLLBACK— откатывает изменения (если что-то пошло не так).
Исправленный пример:
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE user_id = 1;
UPDATE accounts SET balance = balance + 100 WHERE user_id = 2;
COMMIT; -- Если обе операции успешны
-- Или ROLLBACK; -- Если вторая операция failed
ACID — «кислотные» свойства транзакций 🧪
- Atomicity (Атомарность) — Всё или ничего.
- Consistency (Согласованность) — Данные всегда в валидном состоянии.
- Isolation (Изолированность) — Транзакции не мешают друг другу.
- Durability (Долговечность) — После
COMMITизменения сохраняются даже при сбое.
Практика: реалистичные сценарии 💻
Сценарий 1: Интернет-магазин 🛒
BEGIN;
INSERT INTO orders (user_id, product_id) VALUES (5, 42);
UPDATE inventory SET quantity = quantity - 1 WHERE product_id = 42;
-- Проверяем, есть ли ещё товары
IF (SELECT quantity FROM inventory WHERE product_id = 42) < 0 THEN
ROLLBACK;
ELSE
COMMIT;
END IF;
Сценарий 2: Бронирование билетов 🎭
BEGIN;
-- Блокируем место на время транзакции
SELECT * FROM seats WHERE seat_id = 14 FOR UPDATE;
INSERT INTO bookings (user_id, seat_id) VALUES (7, 14);
COMMIT;
Тонкости и подводные камни ⚠️
- Вложенные транзакции — Не все СУБД поддерживают. В PostgreSQL можно использовать
SAVEPOINT. - Автокоммит — По умолчанию включён. Для работы с транзакциями его нужно отключить.
- Долгие транзакции — Могут блокировать другие операции.
Пример с SAVEPOINT:
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE user_id = 1;
SAVEPOINT checkpoint;
UPDATE accounts SET balance = balance + 100 WHERE user_id = 2;
-- Если ошибка:
ROLLBACK TO checkpoint;
-- Или продолжить:
RELEASE checkpoint;
COMMIT;
Как отлаживать транзакции? 🐞
1. Логируйте SQL-запросы.
2. Используйте RETURNING для проверки изменённых данных:
BEGIN;
UPDATE products SET price = price * 1.1
WHERE category = 'Electronics'
RETURNING id, price;
COMMIT;
3. Проверяйте статус транзакции в СУБД (например, SHOW TRANSACTION STATUS в PostgreSQL).
Итоги: когда использовать? 🎯
✅ Используйте транзакции, когда:
- Операции должны быть выполнены как единое целое.
- Данные должны оставаться согласованными.
- Есть риск параллельных изменений.
❌ Не нужны, если:
- Вы делаете простой SELECT.
- Изменения не связаны между собой.