Поддержка транзакций: BEGIN, COMMIT, ROLLBACK

Что такое транзакции и зачем они нужны? 🔄

Транзакция — это последовательность SQL-операций, которая либо выполняется целиком, либо не выполняется вообще. Представьте банковский перевод:

  • Списали деньги с одного счёта → Зачислили на другой.

Если что-то пошло не так (например, отключили свет), транзакция гарантирует, что деньги не «исчезнут» где-то посередине.

Пример без транзакций:

UPDATE accounts SET balance = balance - 100 WHERE user_id = 1;
-- Ой, сервер упал здесь!
UPDATE accounts SET balance = balance + 100 WHERE user_id = 2;

Результат: у первого пользователя деньги списались, а второй их не получил. 💸


Три ключевые команды 🛠️

  1. BEGIN — стартует транзакцию.
  2. COMMIT — подтверждает изменения (всё прошло успешно).
  3. 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;

Тонкости и подводные камни ⚠️

  1. Вложенные транзакции — Не все СУБД поддерживают. В PostgreSQL можно использовать SAVEPOINT.
  2. Автокоммит — По умолчанию включён. Для работы с транзакциями его нужно отключить.
  3. Долгие транзакции — Могут блокировать другие операции.

Пример с 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.
  • Изменения не связаны между собой.
Скрыть рекламу навсегда

🧠 Учёба без воды и зубрёжки

Закрытый Boosty с наработками опытного преподавателя.

Объясняю сложное так, чтобы щелкнуло.

🚀 Забрать доступ к Boosty