**Фантомное чтение (phantom reads).** В результатах повторяющегося запроса появляются и исчезают строки, которые в данный момент модифицирует параллельная транзакция. ^ebb2ec
Эта проблема присутствует на уровне изоляции [Repeatable read](Repeatable%20read.md), [Read committed](Read%20committed.md) и [Read uncommitted](Read%20uncommitted.md).
Рассмотрим пример. Открываем первую транзакцию. Запрашиваем количество строк в таблице пользователей, получаем ответ 2. Далее стартуем вторую транзакцию, а поток с первой транзакцией засыпает. Вторая транзакция добавляет новую запись в таблицу пользователей и коммитит изменения. После этого первая транзакция продолжается. Снова запрашиваем количество строк, получаем на этот раз ответ 3.
```java
public class PhantomRead {
private static final int ISOLATION_LEVEL = Connection.TRANSACTION_READ_COMMITTED;
public static void main(String[] args) {
try(
final Connection connection = Repository.getConnection();
final Statement statement = connection.createStatement()
statement.executeUpdate("INSERT INTO person(id, balance) values (3, 1000)");
connection.commit();
} catch (SQLException e) {
System.out.println(e.getMessage());
}
}
}
}
```
Чтобы устранить эту проблему, используем самый изолированный уровень [Serializable](Serializable.md). Однако, для PostgreSQL будет достаточно и `REPEATABLE_READ`.
Но мы всё равно установим `SERIALIZABLE`. Теперь в первой транзакции нам дважды возвращается ответ 2, несмотря на то, что в таблице появились новые записи.
## Дополнительные материалы
- [Пример на Java](https://github.com/Example-uPagge/transactional/blob/master/jdbc-transaction/src/main/java/dev/struchkov/example/transaction/problems/PhantomRead.java)