В современных Java-приложениях, работающих с реляционными базами данных, корректное управление транзакциями — ключ к надёжности и согласованности данных. Особенно важно понимать уровни изоляции транзакций, которые определяют, как транзакции взаимодействуют друг с другом и какие аномалии могут возникнуть.
В этой статье мы разберём:
- Что такое уровни изоляции транзакций;
- Какие уровни поддерживает стандарт SQL и PostgreSQL;
- Как управлять ими в Java 11 через JDBC;
- Практические примеры для каждого уровня с демонстрацией поведения в PostgreSQL.
1. Теория: что такое уровень изоляции?
Уровень изоляции транзакции определяет степень, в которой одна транзакция изолирована от изменений, внесённых другими одновременно выполняющимися транзакциями. Чем выше уровень изоляции — тем меньше аномалий, но тем ниже параллелизм и производительность.
Согласно стандарту SQL-92, выделяют четыре уровня изоляции:
В современных Java-приложениях, работающих с реляционными базами данных, корректное управление транзакциями — ключ к надёжности и согласованности данных. Особенно важно понимать уровни изоляции транзакций, которые определяют, как транзакции взаимодействуют друг с другом и какие аномалии могут возникнуть.
В этой статье мы разберём:
- Что такое уровни изоляции транзакций;
- Какие уровни поддерживает стандарт SQL и PostgreSQL;
- Как управлять ими в Java 11 через JDBC;
- Практические примеры для каждого уровня с демонстрацией поведения в PostgreSQL.
1. Теория: что такое уровень изоляции?
Уровень изоляции транзакции определяет степень, в которой одна транзакция изолирована от изменений, внесённых другими одновременно выполняющимися транзакциями. Чем выше уровень изоляции — тем меньше аномалий, но тем ниже параллелизм и производительность.
Согласно стандарту SQL-92, выделяют четыре уровня изоляции:
Dirty Read — чтение незафиксированных («грязных») данных другой транзакции.
Non-Repeatable Read — повторное чтение той же строки даёт разные результаты из-за обновления другой транзакцией.
Phantom Read — повторный запрос возвращает новые строки, добавленные другой транзакцией.
2. PostgreSQL и уровни изоляции
PostgreSQL не поддерживает READ UNCOMMITTED — даже если вы его установите, СУБД автоматически понизит его до READ COMMITTED.
Фактически, PostgreSQL поддерживает три уровня:
- READ COMMITTED (по умолчанию),
- REPEATABLE READ,
- SERIALIZABLE.
Важно: в PostgreSQL уровень REPEATABLE READ также предотвращает Phantom Read, что отличается от стандарта SQL. Это достигается за счёт механизма MVCC (Multi-Version Concurrency Control).
3. Управление уровнями изоляции в Java 11 через JDBC
В Java (начиная с JDBC 1.0, но особенно актуально в Java 11) уровень изоляции устанавливается через метод Connection.setTransactionIsolation(int level).
Константы из java.sql.Connection:
- Connection.TRANSACTION_READ_UNCOMMITTED
- Connection.TRANSACTION_READ_COMMITTED
- Connection.TRANSACTION_REPEATABLE_READ
- Connection.TRANSACTION_SERIALIZABLE
⚠️ Уровень изоляции применяется на уровне соединения, а не транзакции. Лучше устанавливать его до начала транзакции.
4. Практика: примеры для каждого уровня
Для демонстрации будем использовать простую таблицу:
И Java-код с использованием чистого JDBC (без Spring и ORM).
Общая настройка подключения
Пример 1: READ COMMITTED (уровень по умолчанию)
Цель: показать non-repeatable read.
Пример 2: REPEATABLE READ
Цель: показать, что повторные чтения не меняются, даже если другая транзакция обновила данные.
В PostgreSQL REPEATABLE READ гарантирует, что все чтения в рамках транзакции видят снимок (snapshot) базы на момент начала транзакции.
⚠️ Если T2 вставит новую строку, соответствующую условию T1 (например, word = 'hi'), и T1 выполнит SELECT ... WHERE word LIKE 'h%', то в PostgreSQL эта новая строка не появится — то есть phantom read тоже блокируется.
Пример 3: SERIALIZABLE
Цель: предотвратить любые конфликты, даже логические.
Уровень SERIALIZABLE в PostgreSQL использует Serializable Snapshot Isolation (SSI) и может откатывать транзакции при обнаружении потенциальных конфликтов.
5. Рекомендации
- По умолчанию используйте READ COMMITTED — он балансирует между производительностью и согласованностью.
- Для отчётов или аналитики, где важна стабильность данных — REPEATABLE READ.
- SERIALIZABLE — только если логика приложения требует строгой сериализуемости (редко, но бывает).
- Всегда обрабатывайте исключения при использовании SERIALIZABLE — транзакции могут откатываться.
- Не забывайте вызывать setAutoCommit(false) и явно управлять commit()/rollback().
Заключение
Примеры, рассмотренные в статье, можно найти по адресу:
https://github.com/ShkrylAndrei/blog_yandex/blob/main/src/main/java/info/shkryl/level_isolation_transaction_second/IsolationDemo.java