Расшифруйте каждую букву ACID
Транзакция выполняется целиком или не выполняется вовсе. Либо все изменения сохраняются, ни одного.
🟢 Junior Level
ACID — это набор из четырёх свойств, которые гарантируют надёжную обработку транзакций в базе данных.
A — Atomicity (Атомарность)
Транзакция выполняется целиком или не выполняется вовсе. Либо все изменения сохраняются, ни одного.
Пример: При переводе денег с одного счёта на другой должны произойти две операции: списание с первого счёта и зачисление на второй. Если вторая операция завершается с ошибкой — СУБД использует undo log (журнал старых значений), чтобы откатить первую операцию.
C — Consistency (Согласованность)
Транзакция переводит базу данных из одного корректного состояния в другое.
Корректное состояние = все ограничения (FOREIGN KEY, UNIQUE, CHECK, NOT NULL) выполнены. Если хотя бы одно нарушено — состояние некорректное, и СУБД откатит транзакцию.
Пример: Если в базе есть ограничение, что баланс не может быть отрицательным, транзакция не сможет записать отрицательный баланс.
I — Isolation (Изолированность)
Параллельные транзакции не должны влиять друг на друга. Каждая транзакция должна работать так, будто она одна.
Пример: Если два человека одновременно переводят деньги с одного счёта, результаты не должны перемешаться.
D — Durability (Долговечность)
После подтверждения транзакции (COMMIT) изменения сохраняются навсегда, даже если сервер внезапно выключится.
🟡 Middle Level
Как ACID реализуется на практике
Atomicity обеспечивается через логи транзакций:
- Перед изменением данных СУБД записывает старые значения в undo log
- Если транзакция отменяется (ROLLBACK), система восстанавливает данные из лога
- Если происходит сбой питания, redo log помогает восстановить committed транзакции
Consistency работает на двух уровнях:
- Database-level: FOREIGN KEY, UNIQUE, CHECK ограничения, типы данных
- Application-level: Бизнес-правила, которые разработчик должен обеспечить сам (например, сумма переводов должна быть равна общей сумме)
Isolation реализуется через:
- Pessimistic Locking: Явные блокировки строк (SELECT FOR UPDATE)
- MVCC (Multi-Version Concurrency Control) — СУБД хранит несколько версий одной строки одновременно. Каждая версия привязана к ID транзакции, которая её создала. Благодаря этому читатели не блокируют писателей.
Durability обеспечивается через:
- Write-Ahead Logging (WAL): Данные сначала пишутся в лог на диск, потом в файлы данных.
Зачем: если сервер упадёт после COMMIT, но до записи в основной файл данных, WAL позволит восстановить изменения при перезапуске.
- fsync(): Гарантирует физическую запись на диск, а не в кэш ОС
- Group Commit: Группировка нескольких подтверждений в одну дисковую операцию
Типичные ошибки
- Путать Consistency (из ACID) с консистентностью в распределённых системах (CAP theorem)
- Думать, что Isolation означает полное отсутствие влияния — на уровнях ниже Serializable аномалии возможны
🔴 Senior Level
Глубокое понимание механизмов реализации
Atomicity — Internal Implementation
- Undo Log / Redo Log: В PostgreSQL используется WAL (Write-Ahead Log). Все изменения сначала записываются WAL, затем в data files. При crash recovery WAL replay восстанавливает committed транзакции через redo, а uncommitted откатываются через undo information, хранящееся в самих страницах (heap tuples).
- Shadow Paging: Альтернативный подход (SQLite, Firebird) — изменения вносятся в копию страницы, при коммите указатель переключается.
Consistency — Beyond Constraints
- В распределённых системах ACID-согласованность противопоставляется Eventual Consistency (CAP theorem)
- Application-level invariants: БД не знает, что сумма переводов между счетами должна оставаться неизменной — это ответственность разработчика
- Deferred constraints: PostgreSQL позволяет отложить проверку constraints до конца транзакции (DEFERRABLE)
Isolation — MVCC Deep Dive
- PostgreSQL MVCC: Каждая строка хранит xmin и xmax — transaction IDs, которые определяют видимость. Читатели не блокируют писателей и наоборот.
Актуально для PostgreSQL 14-16. Детали реализации могут меняться между мажорными версиями.
- PostgreSQL SSI (Serializable Snapshot Isolation): Начиная с 9.1, PostgreSQL использует SSI для Serializable уровня. Система отслеживает read/write dependencies и при обнаружении конфликта прерывает транзакцию с ошибкой
serialization failure. - Trade-off: Идеальная изоляция (Serializable) обходится дорого. Большинство систем работают на Read Committed, допуская определённые аномалии.
Durability — Production Nuances
- synchronous_commit = off в PostgreSQL повышает throughput, но создаёт риск потери ~0.5-1 сек данных при crash
- fsync() overhead: На некоторых SSD/fsync может быть дорогим. Важно учитывать при benchmarking
- Group Commit: Оптимизация, группирующая несколько транзакций в одну I/O операцию для снижения overhead
- Battery-backed RAID controllers: В enterprise-средах аппаратные контроллеры с батареями гарантируют durability даже без fsync
Performance Trade-offs
- Отключение synchronous_commit даёт 2-5x throughput, но с риском потери данных
- MVCC требует хранения multiple row versions → table bloat → VACUUM overhead
- Serializable уровень требует retry logic в приложении
Production Recommendations
- Для большинства use cases: Read Committed + правильная обработка ошибок
- Для финансовых транзакций: Serializable с retry logic
- Мониторить txid exhaustion в PostgreSQL (32-bit transaction IDs)
- Настраивать autovacuum aggressively для предотвращения bloat при высокой write нагрузке
🎯 Шпаргалка для интервью
Обязательно знать:
- ACID = Atomicity, Consistency, Isolation, Durability — 4 свойства надёжных транзакций
- Atomicity = всё или ничего, реализуется через undo/redo log
- Consistency = переход из одного валидного состояния в другое (constraints + application invariants)
- Isolation = параллельные транзакции не влияют друг на друга (MVCC, locks)
- Durability = COMMIT = данные сохранены навсегда (WAL, fsync)
- MVCC — ключевой механизм: PostgreSQL хранит xmin/xmax на каждую строку
- Durability обеспечивается Write-Ahead Logging: сначала лог на диск, потом данные
- На Serializable уровень в PostgreSQL используется SSI (Serializable Snapshot Isolation) с отслеживанием RW-dependencies
Частые уточняющие вопросы:
- Чем Consistency в ACID отличается от Consistency в CAP? — ACID Consistency = constraints БД, CAP Consistency = все ноды видят одни данные
- Что будет при сбое питания после COMMIT? — WAL replay восстановит данные при перезапуске
- Почему PostgreSQL MVCC не требует блокировок при чтении? — Каждая строка имеет версии, привязанные к transaction ID
- Что такое Deferred Constraints? — Constraints, проверка которых откладывается до COMMIT (DEFERRABLE в PostgreSQL)
Красные флаги (НЕ говорить):
- “Consistency в ACID — это то же самое, что eventual consistency” — это разные концепции
- “Isolation означает полное отсутствие влияния транзакций” — на уровнях ниже Serializable аномалии возможны
- “Durability = данные сразу на диск” — сначала WAL, потом async flush в data files
Связанные темы:
- [[2. Какие уровни изоляции транзакций существуют]]
- [[11. Какой уровень изоляции по умолчанию в PostgreSQL]]
- [[18. Что такое rollback в транзакциях]]
- [[6. Что такое Serializable]]