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

В чем разница между уровнями изоляции Read Committed и Read Uncommitted?

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

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

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

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

# Разница между уровнями изоляции Read Committed и Read Uncommitted

Основное понимание уровней изоляции

Уровни изоляции (Isolation Levels) в SQL определяют, как транзакции изолированы друг от друга. Они контролируют видимость изменений, выполняемых одной транзакцией, для других транзакций.

Существует 4 стандартных уровня изоляции (по ACID модели):

  1. Read Uncommitted (самый низкий уровень изоляции)
  2. Read Committed
  3. Repeatable Read
  4. Serializable (самый высокий уровень изоляции)

Read Uncommitted

Read Uncommitted - это самый низкий уровень изоляции. Он позволяет читать грязные (изменения, которые еще не закоммичены) данные от других транзакций.

-- Транзакция 1 (ACID violation)
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
BEGIN TRANSACTION;
  SELECT balance FROM accounts WHERE id = 1; -- Может вернуть грязные данные
COMMIT;

Характеристики:

  • Позволяет читать грязные данные (dirty reads)
  • Не блокирует чтение
  • Самый быстрый уровень
  • Почти не используется на production
  • Может привести к неконсистентности данных

Проблема: Dirty Reads

Транзакция A                  Транзакция B
│                             │
BEGIN;                        │
│                             BEGIN;
│                             UPDATE accounts SET balance = 500
│                             WHERE id = 1;
│                             (не закоммичено)
│                             │
SELECT balance                │
FROM accounts                 │
WHERE id = 1;                 │
→ Видит 500 (грязное!)        │
│                             │
│                             ROLLBACK;
│                             (Данные откатились!)
COMMIT;                       │
└─────────────────────────────┘

Результат: Транзакция A видела данные, которых никогда не было на самом деле!

Read Committed

Read Committed - это второй уровень изоляции. Он гарантирует, что читаются только закоммиченные данные, но не гарантирует, что данные останутся теми же в течение транзакции.

-- Транзакция 1 (правильно)
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
BEGIN TRANSACTION;
  SELECT balance FROM accounts WHERE id = 1; -- Видит только закоммиченные данные
COMMIT;

Характеристики:

  • Не позволяет читать грязные данные (избегает dirty reads)
  • Может быть проблема с non-repeatable reads
  • Может быть проблема с phantom reads
  • Хороший баланс между производительностью и безопасностью
  • Уровень по умолчанию в большинстве DBMS (Oracle, PostgreSQL)
  • Использует блокировки чтения/записи

Проблема: Non-Repeatable Reads

Транзакция A                  Транзакция B
│                             │
BEGIN;                        │
│                             BEGIN;
SELECT balance FROM accounts  │
WHERE id = 1;                 │
→ balance = 100               │
│                             │
│                             UPDATE accounts
│                             SET balance = 500
│                             WHERE id = 1;
│                             COMMIT;
│                             │
SELECT balance FROM accounts  │
WHERE id = 1;                 │
→ balance = 500 (ЭТО ДРУГОЕ!) │
│                             │
COMMIT;                       │
└─────────────────────────────┘

Результат: В одной транзакции одни и те же данные читаются по-разному!

Сравнительная таблица

ПроблемаRead UncommittedRead Committed
Dirty Reads✅ Возможны❌ Не возможны
Non-Repeatable Reads✅ Возможны✅ Возможны
Phantom Reads✅ Возможны✅ Возможны
БлокировкиНетДа (write locks)
ПроизводительностьОчень быстроНормально
СогласованностьОчень низкаяХорошая
ИспользованиеРедкоЧасто (default)

Типы проблем в транзакциях

1. Dirty Read (Грязное чтение)

Чтение данных, которые еще не закоммичены в другой транзакции.

-- Используется только в Read Uncommitted
TRANSACTION A            TRANSACTION B
BEGIN;                   
                         BEGIN;
                         UPDATE account SET balance = 0; -- Ошибка!
SELECT balance;          
→ 0 (грязные данные)     
                         ROLLBACK; -- Ошибка откатила
COMMIT;                  

2. Non-Repeatable Read (Повторяющееся чтение)

Чтение одних и тех же данных дает разные результаты в одной транзакции.

TRANSACTION A            TRANSACTION B
BEGIN;                   BEGIN;
SELECT * FROM user
WHERE id = 1;
→ name = 'John'
                         UPDATE user SET name = 'Jane'
                         WHERE id = 1;
                         COMMIT;
SELECT * FROM user
WHERE id = 1;
→ name = 'Jane' (другое!)
COMMIT;

3. Phantom Read (Фантомное чтение)

Новые строки появляются или исчезают между двумя SELECT запросами одной транзакции.

TRANSACTION A            TRANSACTION B
BEGIN;                   BEGIN;
SELECT COUNT(*) FROM users
WHERE age > 30;
→ 5 строк
                         INSERT INTO users VALUES (...) 
                         WHERE age = 35;
                         COMMIT;
SELECT COUNT(*) FROM users
WHERE age > 30;
→ 6 строк (фантомная!)
COMMIT;

Практический пример в Java

Установка уровня изоляции

// Spring Data JPA
@Transactional(isolation = Isolation.READ_UNCOMMITTED)
public void transferMoney(Long fromId, Long toId, BigDecimal amount) {
    Account from = accountRepository.findById(fromId).orElseThrow();
    Account to = accountRepository.findById(toId).orElseThrow();
    
    from.setBalance(from.getBalance().subtract(amount));
    to.setBalance(to.getBalance().add(amount));
    
    accountRepository.save(from);
    accountRepository.save(to);
}

// Лучше использовать READ_COMMITTED
@Transactional(isolation = Isolation.READ_COMMITTED)
public void transferMoney(Long fromId, Long toId, BigDecimal amount) {
    // Гарантирует чтение закоммиченных данных
}

Пример с JDBC

public void demonstrateIsolationLevels() throws SQLException {
    Connection conn = DriverManager.getConnection("jdbc:postgresql://localhost/db", "user", "pass");
    
    // Read Uncommitted
    conn.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
    
    // Read Committed (default)
    conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
    
    // Repeatable Read
    conn.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);
    
    // Serializable
    conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
}

Когда использовать каждый уровень

Read Uncommitted

// ❌ НЕ используйте на production
// ✅ Используйте только для статистики и аналитики, где точность не критична

@Transactional(isolation = Isolation.READ_UNCOMMITTED)
public void getApproximateStats() {
    // Примерные статистические данные
    // Очень быстро, но может быть неточно
}

Read Committed (рекомендуется)

// ✅ Используйте в большинстве случаев
@Transactional(isolation = Isolation.READ_COMMITTED)
public void processUserRegistration(UserDTO userDTO) {
    User user = new User(userDTO);
    userRepository.save(user); // Видит только закоммиченные данные
}

Влияние на производительность

Produce Uncommitted
████████████████████ - Очень быстро (нет блокировок)

Read Committed
████████████ - Нормально (write locks)

Repeatable Read
████████ - Медленнее (read и write locks)

Serializable
████ - Очень медленно (полная сериализация)

Таблица показателей всех уровней изоляции

УровеньDirty ReadsNon-Rep. ReadsPhantomСкорость
READ_UNCOMMITTED★★★★★
READ_COMMITTED★★★★
REPEATABLE_READ★★★
SERIALIZABLE★★

Выводы

  1. Read Uncommitted позволяет читать грязные (незакоммиченные) данные - очень редко используется
  2. Read Committed гарантирует чтение только закоммиченных данных - рекомендуется в большинстве случаев
  3. Read Committed может иметь проблемы с non-repeatable и phantom reads
  4. Выбирайте Read Committed как баланс между безопасностью и производительностью
  5. Увеличивайте уровень изоляции (к Serializable) только если это критично для данных
  6. PostgreSQL/Oracle по умолчанию используют Read Committed
  7. Используйте оптимистичные блокировки (версионирование) вместо повышения уровня изоляции для лучшей производительности
В чем разница между уровнями изоляции Read Committed и Read Uncommitted? | PrepBro