Мы уже упоминали ранее в курсе, что такое транзакция. Напоминаем, это — последовательность операций, которая должна выполняться как единое целое. Ну вот если нужно сделать банковский перевод. В таком случае мы снимаем деньги с одного счёта и зачисляем их на другой. Если одно из этих действий не удастся (например, деньги списались, но не зачислились), это создаст уйму сложностей. Именно здесь транзакции приходят на помощь.
Транзакция либо выполнится полностью, либо не выполнится вовсе. Это называется принципом "всё или ничего".
BEGIN;
-- Уменьшаем баланс на одном счёте
UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;
-- Увеличиваем баланс на другом счёте
UPDATE accounts SET balance = balance + 100 WHERE account_id = 2;
COMMIT; -- Применяем изменения
Если что-то пойдёт не так, можно откатить изменения с помощью ROLLBACK.
Что такое ACID-свойства транзакций
Когда мы говорим о транзакциях в PostgreSQL (и вообще в реляционных базах данных), часто упоминается аббревиатура ACID — это не про химию. ACID расшифровывается как Atomicity (атомарность), Consistency (согласованность), Isolation (изоляция), Durability (надёжность). Эти четыре свойства обеспечивают, чтобы данные обрабатывались безопасно, последовательно и без сюрпризов.
Атомарность (Atomicity)
Транзакция выполняется целиком или не выполняется вообще. Если внутри неё что-то пошло не так — всё откатывается. Представьте: вы переводите деньги, и вдруг ошибка — либо всё отменяется, либо перевод происходит полностью. Никаких "половинчатых" операций.
Согласованность (Consistency)
После завершения транзакции база остаётся в корректном, логичном состоянии. Все правила, ограничения и связи между таблицами должны соблюдаться. Например, если у вас запрещён отрицательный баланс, транзакция с нарушением просто не будет сохранена.
Изоляция (Isolation)
Пока одна транзакция не завершилась, другая не должна видеть её промежуточные данные. Это защита от странных эффектов, когда вы видите «неопределённое» состояние данных. Представьте, что в интернет-магазине деньги уже списали, а товар ещё не добавили в заказ — не очень приятно, правда?
Надёжность (Durability)
Если транзакция завершилась успешно, все её изменения гарантированно сохраняются. Даже если сразу после этого выключили электричество — данные останутся в базе. Это как нажать "Сохранить" и быть уверенным, что всё точно на месте.
Вот эти четыре свойства — и есть основа того, почему транзакции считаются надёжным механизмом в работе с базами данных.
Примеры сценариев применения транзакций
Теория — это хорошо, но настоящая сила транзакций проявляется в реальных задачах. Именно в таких ситуациях — с деньгами, связанными таблицами или массовыми изменениями — транзакции становятся незаменимым инструментом. Они помогают не просто выполнять операции, а делать это уверенно, без риска потерять данные или оставить базу в «полуработающем» состоянии.
Вот несколько типичных примеров, где транзакции действительно спасают ситуацию:
1. Обработка платежей
Когда клиент переводит деньги с одного счёта на другой, транзакция гарантирует, что деньги не исчезнут ни туда, ни сюда:
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;
UPDATE accounts SET balance = balance + 100 WHERE account_id = 2;
COMMIT;
Если на первом счёте недостаточно средств, можно откатить изменения:
BEGIN;
UPDATE accounts SET balance = balance - 500 WHERE account_id = 1;
-- Ой, баланс отрицательный!
ROLLBACK;
2. Обновление связанных таблиц
Представьте, что вы обновляете статус студента на "выпущен" и одновременно добавляете запись в таблицу "выпускники":
BEGIN;
UPDATE students SET status = 'graduated' WHERE student_id = 42;
INSERT INTO graduates (student_id, graduation_date) VALUES (42, '2023-06-10');
COMMIT;
Если одна из операций не удалась (например, произошла ошибка в INSERT), база данных вернёт начальное состояние.
3. Массовое обновление данных
Транзакции полезны для выполнения больших обновлений, например:
BEGIN;
UPDATE orders SET status = 'completed' WHERE delivery_date < CURRENT_DATE;
COMMIT;
Если сервер упал или вы обнаружили, что обновление пошло не туда, вы можете откатить изменения в любой момент!
Команды для работы с транзакциями
PostgreSQL предоставляет несколько ключевых команд:
BEGIN: начинает новую транзакцию:BEGIN;COMMIT: фиксирует (сохраняет) все изменения, сделанные в рамках транзакции:COMMIT;
ROLLBACK: откатывает все изменения, сделанные в текущей транзакции:
ROLLBACK;
Пример полного цикла
BEGIN;
-- Некоторые операции
UPDATE accounts SET balance = balance - 200 WHERE account_id = 1;
UPDATE accounts SET balance = balance + 200 WHERE account_id = 2;
-- Решили откатить изменения
ROLLBACK;
-- Начинаем снова
BEGIN;
-- Те же операции, но другой перевод
UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;
UPDATE accounts SET balance = balance + 100 WHERE account_id = 2;
-- Завершаем транзакцию
COMMIT;
Жизнь транзакций вне учебника
Интернет-магазины. Многие платформы используют транзакции для управления заказами и платежами. Например, заказ выполняется только в случае успешной оплаты. Если что-то пошло не так, заказ автоматически отменяется.
Банковские системы. Транзакции защищают ваши деньги от проблем вроде неожиданного отключения света.
История транзакций. PostgreSQL хранит журналы WAL (Write-Ahead Logging) для восстановления данных в случае сбоя. Это магия, которая делает транзакции надёжными.
В следующей лекции мы разберём команды BEGIN, COMMIT и ROLLBACK более подробно, а также посмотрим на примеры массовых операций и частичных откатов с SAVEPOINT. До встречи!
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ