← Назад к вопросам

Какие знаешь уровни транзакций?

1.0 Junior🔥 141 комментариев
#Базы данных и SQL

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Уровни изоляции транзакций в СУБД

Уровни изоляции транзакций — это фундаментальная концепция в работе с базами данных. Они регулируют, как конкурирующие транзакции видят данные друг друга и определяют баланс между консистентностью и производительностью.

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'и!