Что такое транзакция в контексте баз данных?

Ответ

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

  • Atomicity (Атомарность): Все операции транзакции выполняются как одно целое. Невозможно частичное выполнение.
  • Consistency (Согласованность): Транзакция переводит базу из одного согласованного состояния в другое, соблюдая все бизнес-правила и constraints (ограничения).
  • Isolation (Изолированность): Параллельные транзакции не должны влиять друг на друга. Уровни изоляции (Read Committed, Repeatable Read, Serializable) определяют степень этого влияния и компромисс с производительностью.
  • Durability (Долговечность): После успешного завершения (commit) изменения, внесенные транзакцией, сохраняются навсегда, даже в случае сбоя системы.

Практический пример на SQL:

BEGIN TRANSACTION; -- Начало транзакции

UPDATE accounts SET balance = balance - 100.00 WHERE id = 1; -- Списание
UPDATE accounts SET balance = balance + 100.00 WHERE id = 2; -- Зачисление
-- Предположим, здесь проверяется, что баланс не ушел в минус.
-- Если всё успешно:
COMMIT; -- Фиксация изменений
-- Если что-то пошло не так (например, недостаточно средств):
-- ROLLBACK; -- Откат всех изменений в этой транзакции

В приложениях я использую транзакции для операций, которые должны быть атомарными: финансовые переводы, регистрация пользователя (создание записи + отправка письма), синхронное обновление нескольких связанных таблиц.

Ответ 18+ 🔞

Давай разберем эту вашу транзакционную магию, а то звучит страшно, а на деле — проще пареной репы, если не лезть в дебри.

Представь, что ты в баре. Ты подходишь к стойке и говоришь: «Дайте мне два пива и пачку чипсов». Это твоя транзакция. Официант (это наша СУБД) либо выполняет ВСЁ твоё требование — приносит и пиво, и чипсы (это COMMIT), либо, если чипсы кончились, говорит: «Извини, чувак, чипсов нет, пиво тоже не дам, иди на хуй». И ты остаешься с пустыми руками (это ROLLBACK). Никакого «одно пиво без чипсов» — либо всё, либо нихуя. Это и есть атомарность (Atomicity). Либо всё успешно, либо откатываемся к началу, как будто ты и не заказывал.

Теперь про согласованность (Consistency). Это чтобы правила бара не нарушались. Ты не можешь заказать пиво, если тебе нет 18, или уйти в минус по счету. База данных — та еще хитрая жопа, она следит, чтобы после твоей операции все её внутренние законы (constraints, триггеры) не были нарушены. Перевел деньги — проверь, чтобы у отправителя не ушло в минус. Не прошла проверка — всё, откат, иди гуляй.

Изолированность (Isolation) — это вообще отдельная песня, ёпта. Представь, что в баре кроме тебя еще овердохуища народа. Ты видишь, как официант несет два пива к столику №2. Ты думаешь: «Отлично, чипсы, наверное, уже готовят». А на самом деле парень из №2 только что отменил заказ, и чипсов не будет. Ты увидел промежуточное, «грязное» состояние. Уровни изоляции — это как раз правила, определяющие, какую хуйню параллельные транзакции могут видеть друг у друга. Самый строгий уровень (SERIALIZABLE) — это как если бы ты был в баре один, все остальные ждут снаружи. Надежно, но медленно, блядь. Обычно используют READ COMMITTED — ты видишь только зафиксированные другими результаты. Не висит у тебя перед носом недопитое пиво, которое кто-то еще может вернуть.

Ну и долговечность (Durability). Это когда ты уже расплатился, получил свои пиво и чипсы, сел за столик и даже отхлебнул. В этот момент с потолка падает люстра и разбивает твою кружку. Изменения уже зафиксированы! Ты получил товар. Точно так же, после COMMIT данные записываются так, чтобы пережить даже внезапное выключение сервера. Они уже не в оперативке, а на жестком диске, в надежном месте. Накрылся медным тазом сервер — а твой перевод денег уже в истории и никуда не денется.

Вот твой же пример, но с комментариями от души:

BEGIN TRANSACTION; -- Всё, понеслась, начинаем нашу авантюру. Все следующие действия — одна пачка.

UPDATE accounts SET balance = balance - 100.00 WHERE id = 1; -- Дернули с первого счёта сотку.
UPDATE accounts SET balance = balance + 100.00 WHERE id = 2; -- Закинули второму на счёт.
-- А вот тут, чувак, могла бы быть проверка. Типа, а не ушёл ли первый в минус? Если ушёл — волнение ебать, всё пропало.

-- Если к этому моменту всё гладко, ни одна проверка не ругнулась...
COMMIT; -- Ёб твою мать, красота! Фиксируем. Деньги переведены, операция завершена. Все видят новый баланс.

-- А если что-то пошло не так (недостаточно средств, ошибка сети, ещё какая-то муда)...
-- ROLLBACK; -- Всё, пизда рулю. Откатываем ВСЕ изменения этой транзакции. Как будто этих двух UPDATE-ов и не было. Первому вернули сотку, второй её не получал. Целостность на месте.

Где это юзать? Да везде, где важен принцип «пан или пропал»!

  • Финансы: Перевод денег — это классика. Списать И зачислить. Нельзя списать и не зачислить — это доверия ебать ноль.
  • Регистрация пользователя: Создал запись в users + создал запись в profiles + отправил приветственное письмо. Если письмо не отправилось — откатываем всё и просим юзера попробовать снова, а не оставляем в системе полупидора без профиля.
  • Сложное обновление: Нужно обновить заказ в orders и количество товара на складе в warehouse. Сделал в одной транзакции — и не будет ситуации «заказ оформлен, а товара как бы нет».

Короче, транзакция — это твой надёжный способ не накосячить в связках операций. Без неё в параллельном мире — один сплошной распиздяй и бардак.

Видео-ответы