Ответ
Нет, не защищает. В PostgreSQL REPEATABLE READ реализован на основе снимка состояния (snapshot isolation), который гарантирует только отсутствие грязного и неповторяющегося чтения, но не предотвращает фантомное чтение.
- Гарантии
REPEATABLE READв PostgreSQL: Транзакция видит только те данные, которые были зафиксированы до её начала. Созданный в начале транзакции снимок данных не изменяется. - Отсутствующая гарантия: Если другая параллельная транзакция добавит новые строки (INSERT), удовлетворяющие условиям запроса первой транзакции, и зафиксирует их, то при повторном выполнении того же запроса первая транзакция увидит эти новые «фантомные» строки.
Пример фантомного чтения в PostgreSQL при REPEATABLE READ:
-- Сессия 1
BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;
SELECT * FROM employees WHERE department_id = 5; -- Возвращает 3 строки
-- Сессия 2 (параллельно)
BEGIN;
INSERT INTO employees (name, department_id) VALUES ('Alice', 5);
COMMIT; -- Фиксирует новую строку с department_id = 5
-- Сессия 1 (повторяет запрос)
SELECT * FROM employees WHERE department_id = 5; -- Может вернуть 4 строки! Фантом.
COMMIT;
Как защититься? Для полной защиты от фантомного чтения в PostgreSQL необходимо использовать уровень изоляции SERIALIZABLE. На этом уровне система обнаруживает потенциальные конфликты, приводящие к фантомам, и откатывает одну из транзакций.