Какие проблемы возникают с транзакциями при параллельном выполнении?

«Какие проблемы возникают с транзакциями при параллельном выполнении?» — вопрос из категории Базы данных, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Параллельное выполнение транзакций в СУБД может привести к конфликтам и нарушению целостности данных. Основные проблемы описываются аномалиями чтения/записи.

Ключевые аномалии параллелизма:

  1. «Грязное» чтение (Dirty Read): Транзакция читает незафиксированные данные другой транзакции, которая может быть откачена.
  2. Неповторяющееся чтение (Non-Repeatable Read): В рамках одной транзакции повторное чтение одной и той же строки возвращает разные значения из-за её обновления другой транзакцией.
  3. Фантомное чтение (Phantom Read): При повторном выполнении запроса с одинаковым условием появляются новые («фантомные») строки, вставленные другой транзакцией.
  4. Потерянное обновление (Lost Update): Две транзакции читают одну запись, затем обе обновляют её, и результат первой транзакции перезаписывается второй.

Механизмы управления параллелизмом:

  • Уровни изоляции транзакций: СУБД предлагают уровни (от наименее строгого к наиболее строгому): READ UNCOMMITTED, READ COMMITTED, REPEATABLE READ, SERIALIZABLE. Каждый уровень предотвращает определённый набор аномалий.
  • Блокировки (пессимистичный контроль): СУБД или приложение явно блокирует данные (SELECT ... FOR UPDATE).
  • Управление версиями (оптимистичный контроль): Проверка версии записи при обновлении (например, через поле version или timestamp).

Пример пессимистичной блокировки в SQL:

BEGIN TRANSACTION;
SELECT * FROM accounts WHERE id = 1 FOR UPDATE; -- Блокировка строки
-- ... логика обновления ...
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
COMMIT;