Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Уровни изоляции транзакций в СУБД
Уровни изоляции транзакций — это фундаментальная концепция в работе с базами данных. Они регулируют, как конкурирующие транзакции видят данные друг друга и определяют баланс между консистентностью и производительностью.
1. Read Uncommitted (читать неподтвёрждённые данные)
Это самый низкий уровень изоляции. Транзакция может читать данные, которые ещё не закоммичены другой транзакцией.
Проблемы:
- Грязное чтение (Dirty Read) — чтение неподтвёрждённых данных
- Максимальная производительность, но минимальная безопасность
Connection conn = dataSource.getConnection();
conn.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
conn.setAutoCommit(false);
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT balance FROM accounts WHERE id = 1");
rs.next();
int balance = rs.getInt("balance"); // Может быть неподтвёрждённое значение
conn.commit();
2. Read Committed (читать подтвёрждённые данные)
Это стандартный уровень во многих БД. Транзакция видит только подтвёрждённые данные.
Решает:
- Грязные чтения исключены
Остаются проблемы:
- Non-repeatable Read — если одна транзакция обновляет данные, вторая увидит новые значения при повторном чтении
Connection conn = dataSource.getConnection();
conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
conn.setAutoCommit(false);
int balance1 = getBalance(conn, 1); // balance = 100
// Другая транзакция обновляет данные и закоммичивает
int balance2 = getBalance(conn, 1); // balance может быть 150
if (balance1 != balance2) {
System.out.println("Non-repeatable read occurred!");
}
conn.commit();
3. Repeatable Read (повторяемое чтение)
Транзакция видит снимок данных на момент своего начала. Гарантирует, что одни и те же данные прочитанные несколько раз имеют одно значение.
Решает:
- Грязные чтения
- Non-repeatable reads
Остаются проблемы:
- Phantom Read — если другая транзакция добавляет новые строки, они могут появиться в результате запроса
Connection conn = dataSource.getConnection();
conn.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);
conn.setAutoCommit(false);
int count1 = countAccounts(conn); // count = 5
// Другая транзакция вставляет новый аккаунт
int count2 = countAccounts(conn); // count может быть 6 (Phantom Read)
conn.commit();
4. Serializable (сериализуемость)
Это самый высокий уровень изоляции. Транзакции выполняются так, как будто бы они выполнялись последовательно.
Преимущества:
- Все проблемы исключены
- Максимальная консистентность
Недостатки:
- Максимальная блокировка
- Низкая производительность
- Риск deadlock'ов
Connection conn = dataSource.getConnection();
conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
conn.setAutoCommit(false);
Statement stmt = conn.createStatement();
stmt.executeUpdate("UPDATE accounts SET balance = balance - 100 WHERE id = 1");
stmt.executeUpdate("UPDATE accounts SET balance = balance + 100 WHERE id = 2");
conn.commit();
Практический пример на Spring Boot с JPA
@Service
public class AccountService {
@Transactional(isolation = Isolation.SERIALIZABLE)
public void transferMoney(Long fromId, Long toId, BigDecimal amount) {
Account from = accountRepository.findById(fromId)
.orElseThrow(() -> new AccountNotFoundException(fromId));
Account to = accountRepository.findById(toId)
.orElseThrow(() -> new AccountNotFoundException(toId));
if (from.getBalance().compareTo(amount) < 0) {
throw new InsufficientFundsException();
}
from.setBalance(from.getBalance().subtract(amount));
to.setBalance(to.getBalance().add(amount));
accountRepository.save(from);
accountRepository.save(to);
}
}
Выводы
Выбирай уровень изоляции в зависимости от требований:
- Read Committed — стандарт для большинства приложений
- Repeatable Read — когда нужна консистентность вычислений в одной транзакции
- Serializable — для критичных операций (перевод денег, бронирование)
- Read Uncommitted — только в очень редких случаях при критичности производительности
Помни, что выбор уровня влияет на производительность базы данных и потенциальные deadlock'и!