← Назад к вопросам

Что такое транзакция в базе данных? Какие свойства ACID вы знаете?

2.0 Middle🔥 251 комментариев
#Базы данных и SQL

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI29 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Транзакции в базе данных и свойства ACID

Транзакция — это фундаментальная концепция в системах управления базами данных (СУБД). Она гарантирует надежность и целостность данных при выполнении сложных операций, особенно когда одновременно работают несколько пользователей.

Определение транзакции

Транзакция — это логическая единица работы, состоящая из одной или нескольких операций БД (INSERT, UPDATE, DELETE, SELECT), которые либо выполняются полностью, либо откатываются полностью. Либо все, либо ничего.

Пример транзакции (перевод денег):

BEGIN TRANSACTION;
  UPDATE accounts SET balance = balance - 100 WHERE id = 1;
  UPDATE accounts SET balance = balance + 100 WHERE id = 2;
COMMIT;

Это гарантирует, что либо оба счета обновлены, либо ни один не обновлен (если случилась ошибка).

Зачем нужны транзакции?

Без транзакций:

Counted = 0;
IF balance >= 100:
  balance = balance - 100  # Успешно
  other_balance = other_balance + 100  # ОШИБКА! Связь потеряна

Результат: 100 рублей исчезло из системы.

С транзакциями:

BEGIN TRANSACTION;
  IF balance >= 100:
    balance = balance - 100
    other_balance = other_balance + 100
  ELSE:
    ROLLBACK;  # Ничего не меняется
  COMMIT;  # Либо обе операции, либо ни одна

Свойства ACID

ACID — это четыре ключевых свойства, которые гарантируют надежность транзакций:

1. Atomicity (Атомарность)

Определение: Атомарность гарантирует, что транзакция — это неделимая единица работы. Либо все операции выполняются, либо ни одна.

Принцип: Либо полная фиксация (commit), либо полный откат (rollback). Нет частичных результатов.

Пример:

Передача денег:

BEGIN TRANSACTION;
  UPDATE accounts SET balance = balance - 100 WHERE account_id = 'A';
  UPDATE accounts SET balance = balance + 100 WHERE account_id = 'B';
COMMIT;

Если между двумя UPDATE вернула ошибка:
  - Первый UPDATE откатывается
  - Второй UPDATE не выполняется
  - БД остается в консистентном состоянии

Механизм реализации:

  • WAL (Write-Ahead Logging) — записывается лог до фиксации
  • Undo logs — сохранение старых значений
  • При откате операции воспроизводятся в обратном порядке

Риски нарушения:

  • Crash БД во время фиксации
  • Отключение питания
  • Конфликты с другими транзакциями

2. Consistency (Согласованность)

Определение: Согласованность гарантирует, что транзакция переводит БД из одного консистентного состояния в другое консистентное состояние. Все правила целостности соблюдаются.

Принцип: БД всегда остается в валидном состоянии. Нарушают консистентность:

  • Foreign key constraints
  • Check constraints
  • Unique constraints
  • Domain constraints

Пример:

Правило консистентности: Сумма всех счетов = константе

ДО:    Account_A = 1000, Account_B = 1000, Total = 2000
ТРАНЗАКЦИЯ: Передача 100 от A к B
ПОСЛЕ: Account_A = 900, Account_B = 1100, Total = 2000

Если вместо COMMIT будет ROLLBACK:
ПОСЛЕ ОТКАТЯ: Account_A = 1000, Account_B = 1000, Total = 2000

Примеры нарушения консистентности:

-- Нарушение foreign key
INSERT INTO orders (product_id, ...) VALUES (999, ...);  
-- product_id 999 не существует → ошибка

-- Нарушение check constraint
UPDATE employees SET salary = -1000 WHERE id = 1;
-- salary < 0 запрещено → ошибка

-- Нарушение unique constraint
INSERT INTO users (email) VALUES ('john@example.com');
-- email уже существует → ошибка

Механизм реализации:

  • Проверка констрейнтов ДО коммита
  • Откат при нарушении
  • Каскадные операции (cascading)

3. Isolation (Изоляция)

Определение: Изоляция гарантирует, что одновременно выполняемые транзакции не влияют друг на друга. Каждая транзакция работает так, как будто она выполняется одна.

Принцип: Одна транзакция не видит незаконченные изменения другой транзакции.

Проблемы без изоляции:

Транзакция 1:              Транзакция 2:
ВА 1: READ balance = 1000
ВА 2:                      READ balance = 1000
ВА 3: balance = 1000 - 100 = 900
ВА 4: WRITE balance = 900
ВА 5:                      balance = 1000 + 500 = 1500
ВА 6:                      WRITE balance = 1500

Результат: 1500 (потеря 100 рублей)
Если была изоляция: 1400 (правильно)

Уровни изоляции (от слабого к сильному):

1. READ UNCOMMITTED (самый слабый)

  • Транзакция может видеть незакоммиченные изменения других транзакций
  • Риск: Dirty reads, lost updates
  • Использование: Очень редко (высокая производительность, низкая безопасность)
Транзакция A: UPDATE users SET balance = 100;
              (не закоммичена)
Транзакция B: SELECT balance FROM users;  
              → видит 100 (незакоммиченное)
Транзакция A: ROLLBACK;

Транзакция B используется неправильное значение

2. READ COMMITTED (рекомендуемый)

  • Транзакция видит только закоммиченные данные
  • Риск: Non-repeatable reads, phantom reads
  • Использование: Большинство приложений
  • Performance: хороший баланс
Транзакция A: UPDATE users SET salary = 5000 WHERE id = 1;
              COMMIT;
Транзакция B: SELECT salary FROM users WHERE id = 1;  
              → видит 5000 (закоммичено)

3. REPEATABLE READ

  • Транзакция видит консистентный снимок данных на момент начала
  • Риск: Phantom reads
  • Использование: Когда нужна более высокая изоляция
  • Performance: медленнее
Транзакция A (начало): SELECT COUNT(*) FROM orders;  → 5
Транзакция B: INSERT INTO orders VALUES (...); COMMIT;
Транзакция A (конец): SELECT COUNT(*) FROM orders;  → 5 (все еще видит 5)

4. SERIALIZABLE (самый сильный)

  • Транзакции выполняются так, как если бы они выполнялись последовательно
  • Нет dirty reads, non-repeatable reads, phantom reads
  • Риск: Очень низкая производительность
  • Использование: Критичные операции

Выбор уровня изоляции:

READ UNCOMMITTED < READ COMMITTED < REPEATABLE READ < SERIALIZABLE
Больше производительность → Меньше безопасность

4. Durability (Долговечность)

Определение: Долговечность гарантирует, что закоммиченные данные永远ine сохранятся, даже при сбое системы (crash БД, отключение питания).

Принцип: Один раз закоммичено — данные гарантированно сохранены на диск.

Механизм реализации:

  • WAL (Write-Ahead Logging) — записывается на диск ДО коммита
  • Fsync() — гарантирует запись на физический диск
  • Репликация на несколько физических дисков
  • Резервные копии

Пример:

Процесс коммита:
1. Все изменения записываются в WAL лог на диск
2. Фиксируется commit marker в логе
3. Только потом изменения применяются к основным данным

Если crash происходит на этапе 3:
  → При восстановлении БД прочитает лог и восстановит состояние

Trade-offs:

Полная долговечность (fsync после каждого коммита):
  Плюсы: Максимальная безопасность
  Минусы: Медленно (1000-5000 транзакций/сек)

Отложенная долговечность (fsync раз в несколько секунд):
  Плюсы: Быстро (100000+ транзакций/сек)
  Минусы: Риск потери последних нескольких секунд данных

Примеры нарушения ACID

Нарушение Atomicity:

START TRANSACTION;
  INSERT INTO orders (user_id, product_id, amount) VALUES (1, 5, 100);
  UPDATE inventory SET qty = qty - 1 WHERE product_id = 5;  
  -- ОШИБКА: inventory не существует
ROLLBACK;  → заказ не создан

Нарушение Consistency:

BEGIN TRANSACTION;
  UPDATE accounts SET balance = balance - 100 WHERE id = 1;
  UPDATE accounts SET balance = balance + 100 WHERE id = 999;  
  -- Счет 999 не существует → нарушение foreign key
ROLLBACK;  → оба счета остаются неизменены

Нарушение Isolation:

Транзакция A (Уровень 1): SELECT balance = 1000;
Транзакция B: UPDATE balance = 500; COMMIT;
Транзакция A (Уровень 1): SELECT balance = 500;  
→ Non-repeatable read (видит изменение B)

Нарушение Durability:

BEGIN TRANSACTION;
  UPDATE account SET balance = 0;
COMMIT;  → возвращает OK
[БД падает]
→ Если не было fsync, то данные потеряны

Конфликты между ACID свойствами

Atomicity vs Performance:

  • Гарантировать полную атомарность медленно
  • Компромисс: Аккумулировать изменения в памяти, потом писать пакетами

Isolation vs Performance:

  • SERIALIZABLE уровень очень медленный
  • Большинство приложений используют READ COMMITTED

Consistency vs Flexibility:

  • Строгая консистентность требует проверок
  • Eventual consistency (NoSQL) слабее но быстрее

Durability vs Speed:

  • fsync на каждый коммит = безопасно но медленно
  • Буферизация изменений = быстро но рискованно

Практическое применение

PostgreSQL:

BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED;
  SELECT balance FROM accounts WHERE id = 1;  
  UPDATE accounts SET balance = balance - 100 WHERE id = 1;  
COMMIT;

MySQL (InnoDB):

START TRANSACTION;
  -- Операции
COMMIT;  или ROLLBACK;

MongoDB (Версия 4.0+):

сессия.start_transaction()
try:
  # Операции
  сессия.commit_transaction()
except:
  сессия.abort_transaction()

Лучшие практики

  1. Держи транзакции короткими — минимизирует конфликты
  2. Выбери правильный уровень изоляции — баланс между безопасностью и производительностью
  3. Используй индексы — ускоряет блокировки и откаты
  4. Избегай deadlocks — всегда доступи к ресурсам в одном порядке
  5. Мониторь долгие транзакции — они блокируют других
  6. Используй batch operations — вместо цикла с отдельными транзакциями
  7. Документируй критичные транзакции — объясни почему нужна эта логика
  8. Тестируй отказы — используй chaos engineering

Транзакции и ACID свойства — это фундамент надежности любой системы, работающей с данными. Неправильное использование или непонимание может привести к потере данных, финансовым потерям и проблемам с доверием пользователей.

Что такое транзакция в базе данных? Какие свойства ACID вы знаете? | PrepBro