Короткий ответ
Транзакция — это последовательность операций, выполняемая как единое неделимое целое; ACID (Atomicity, Consistency, Isolation, Durability) описывает гарантии, которые СУБД даёт для транзакций: атомарность, согласованность, изолированность и устойчивость к сбоям.
Как это работает подробнее
Atomicity — все операции применяются целиком или не применяются вовсе (ROLLBACK при ошибке); Consistency — после транзакции данные остаются согласованными с ограничениями БД; Isolation — конкурентные транзакции не видят промежуточных незафиксированных изменений друг друга; Durability — после COMMIT данные гарантированно сохранены даже при сбое благодаря WAL.
Пример кода
example.py
with connection.cursor() as cur:
try:
cur.execute("BEGIN")
cur.execute("UPDATE accounts SET balance = balance - 100 WHERE id = 1")
cur.execute("UPDATE accounts SET balance = balance + 100 WHERE id = 2")
cur.execute("COMMIT")
except Exception:
cur.execute("ROLLBACK")
raiseЧто использовать на практике
- Практика. Оборачивать в транзакцию нужно логически связанные операции — например, списание денег с одного счёта и зачисление на другой, чтобы при сбое после первой операции вторая не «потерялась».
Подводные камни
- Ошибка. Держат транзакцию открытой слишком долго (например, ждут ответа внешнего API внутри транзакции), удерживая блокировки; забывают явный ROLLBACK при обработке исключения, из-за чего соединение остаётся в состоянии прерванной транзакции.