Какие проблемы (аномалии) могут возникать на уровне изоляции транзакций READ COMMITTED?

«Какие проблемы (аномалии) могут возникать на уровне изоляции транзакций READ COMMITTED?» — вопрос из категории SQL и базы данных, который задают на 33% собеседований Data Инженер. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Уровень изоляции READ COMMITTED (чтение зафиксированных данных) является уровнем по умолчанию во многих СУБД (например, PostgreSQL). Он предотвращает «грязное чтение» (Dirty Read), но допускает следующие аномалии:

1. Неповторяющееся чтение (Non-repeatable Read) Одна и та же строка, прочитанная дважды в рамках одной транзакции, может иметь разные значения, потому что другая, параллельная транзакция изменила и зафиксировала эту строку между двумя чтениями.

2. Фантомное чтение (Phantom Read) Набор строк, полученный в результате двух одинаковых запросов в одной транзакции, может различаться из-за того, что другая транзакция добавила или удалила строки, удовлетворяющие условию запроса.

Практический пример в PostgreSQL:

-- Сессия 1 (Транзакция A)
BEGIN; -- Уровень изоляции READ COMMITTED
SELECT balance FROM accounts WHERE user_id = 1; -- Чтение 1: допустим, 100

-- Сессия 2 (Транзакция B) выполняет и коммитит:
BEGIN;
UPDATE accounts SET balance = 50 WHERE user_id = 1;
COMMIT;

-- Сессия 1 снова читает ту же строку:
SELECT balance FROM accounts WHERE user_id = 1; -- Чтение 2: теперь 50 (Non-repeatable Read)
COMMIT;

Как с этим бороться? Для предотвращения этих аномалий нужно использовать более строгий уровень изоляции — REPEATABLE READ или SERIALIZABLE. В REPEATABLE READ СУБД (как PostgreSQL) использует снимки данных (snapshot), чтобы гарантировать, что транзакция видит данные в одном и том же состоянии на протяжении всей своей работы.