Транзакции и ACID
239 мин
Банковский перевод состоит из двух шагов: списать со счёта и зачислить на другой. А если после первого шага сервер выключится? Деньги просто исчезнут. Транзакция этого не допустит.
Всё или ничего
BEGIN;
UPDATE accounts SET balance = balance - 500000 WHERE id = 1;
UPDATE accounts SET balance = balance + 500000 WHERE id = 2;
COMMIT;BEGIN— транзакция началась;COMMIT— сохранить всё;ROLLBACK— отменить всё, как будто ничего не было.
Изменения до COMMIT не видны другим пользователям. При ошибке или обрыве связи база сама отменит транзакцию.
Страховка для себя
Транзакция — ремень безопасности перед опасной командой:
BEGIN;
DELETE FROM dori WHERE yaroqlilik_muddati < '2026-01-01';
SELECT count(*) FROM dori; -- проверяем результат
ROLLBACK; -- или COMMIT, если всё правильноПопробуйте в свободном режиме: загрузите готовую базу, после BEGIN удалите все строки, посмотрите SELECT, затем ROLLBACK — строки на месте.
ACID
Хорошая база гарантирует для транзакций четыре свойства:
| Буква | Название | Простыми словами |
|---|---|---|
| Atomicity | атомарность | всё или ничего |
| Consistency | согласованность | правила (ключи, ограничения) не нарушаются |
| Isolation | изолированность | параллельные транзакции не мешают друг другу |
| Durability | долговечность | после COMMIT данные не пропадут, даже если сервер выключится |
Проблемы параллельной работы
Что может случиться, когда работает много людей сразу:
- грязное чтение — увидеть чужие ещё не сохранённые изменения;
- неповторяемое чтение — дважды прочитали строку в одной транзакции и получили разное;
- фантомы — при повторном подсчёте появились новые строки.
Степень защиты от этого называется уровнем изоляции.
PostgreSQL по умолчанию работает на уровне READ COMMITTED: каждая команда видит только сохранённые данные. При необходимости: BEGIN ISOLATION LEVEL SERIALIZABLE;
Автосохранение
Если транзакция не начата, каждая команда — отдельная транзакция и сохраняется сразу (autocommit). Поэтому DELETE, выполненный без BEGIN, через ROLLBACK не вернуть.
SAVEPOINT — промежуточная точка
BEGIN;
INSERT INTO mijoz (ism) VALUES ('Aziz');
SAVEPOINT birinchi;
INSERT INTO mijoz (ism) VALUES ('Xato');
ROLLBACK TO SAVEPOINT birinchi; -- отменяется только вторая вставка
COMMIT;Запомните
BEGIN … COMMIT— всё сохраняется;ROLLBACK— всё отменяется.- ACID — атомарность, согласованность, изолированность, долговечность.
- Перед опасным изменением пишите
BEGIN.