Как ответить
Транзакция — это атомарное действие с базой данных. Она выполняется целиком или не выполняется вообще. Если на середине операции произошёл сбой, база данных откатится к исходному состоянию.
Основная цель транзакции — обеспечить целостность данных при конкурентном доступе и сбоях. Транзакции следуют принципу ACID:
- Atomicity (Атомарность) — все операции внутри транзакции либо выполняются, либо нет. Пример: при переводе денег со счёта на счёт списание и зачисление должны произойти оба. Если одно не удалось — откат.
- Consistency (Согласованность) — после транзакции данные соответствуют всем правилам БД (например, внешние ключи, CHECK-ограничения). Если перевод делает баланс отрицательным — транзакция откатывается.
- Isolation (Изолированность) — конкурентные транзакции не влияют друг на друга. Если два пользователя одновременно покупают последний товар, только один получит его, второй — ошибку или ожидание.
- Durability (Надёжность) — после успешного COMMIT изменения сохраняются даже при сбое питания. Обычно реализуется через WAL (Write-Ahead Log) — все изменения сначала пишутся в журнал.
Пример на SQL:
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
-- Если на этом этапе сервер упал, деньги не пропадут
COMMIT; -- при ошибке ROLLBACKНа уровне изоляции есть классическая проблема Dirty Read (чтение незафиксированных данных). Стандарт SQL определяет 4 уровня изоляции: от Read Uncommitted до Serializable. В PostgreSQL по умолчанию Read Committed — он читает только COMMIT'нутые версии строк. Это компромисс между производительностью и консистентностью.
В обычных веб-приложениях (например, Spring @Transactional) достаточно Read Committed. Для банковских расчётов лучше Serializable с механизмом optimistic locking.