JavaRush /Курсы /SQL SELF /Введение в уровни изоляции транзакций

Введение в уровни изоляции транзакций

SQL SELF
39 уровень , 4 лекция
Открыта

Представьте, что вы работаете в кафе, в котором один официант проверяет запас тортов на кухне, а другой заполняет заказ на торт от нового клиента. В идеальном мире они оба должны работать с одинаковыми данными о количестве тортов, чтобы избежать ошибок вроде "двойного бронирования". Но в реальном мире могут возникнуть проблемы параллельного выполнения операций.

Вот три основные неприятности, которые могут произойти:

  1. Dirty Read (грязное чтение): Один запрос видит изменения, которые сделаны другим, но ещё не зафиксированы. Если эти изменения будут откатаны, первый запрос окажется наивным, как студент на первом собеседовании.

  2. Non-Repeatable Read (неповторяющееся чтение): Один запрос дважды читает те же данные, но между этими чтениями кто-то другой успевает их изменить. Это как прийти на вокзал, увидеть расписание поездов, вернуться через минуту — и обнаружить, что поезд был отменён. Ну или твой билет купили, пока ты искал деньги :)

  3. Phantom Read (фантомное чтение): Один запрос видит подмножество строк, но между двумя выполнениями кто-то добавляет новые строки, которые влияют на результат. Это как если бы ваша компания проиграла тендер, а потом все заявки кроме вашей и заявки жены мера были отменены.

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

Теперь, когда мы знаем о проблемах, пора заглянуть в инструмент, который PostgreSQL предоставляет для их решения — уровни изоляции транзакции. Это как установка правил для взаимодействия между параллельными транзакциями. Чем выше уровень изоляции, тем больше гарантий, что транзакции не будут друг другу мешать. Однако за это приходится платить сниженными "скоростью обслуживания", то есть производительностью.

Уровни изоляции в PostgreSQL

  1. Read Uncommitted (Чтение неподтверждённых данных):

    • Позволяет чтение изменений, которые еще не были зафиксированы (да, это грязное чтение во всей его красе).
    • В PostgreSQL такой уровень на самом деле реализован как Read Committed, так что в чистом виде он не поддерживается. PostgreSQL отказывается его реализовывать, так как этот подход слишком ненадёжный.
  2. Read Committed (Чтение зафиксированных изменений):

    • Предотвращает грязное чтение.
    • Транзакция видит только те данные, которые были зафиксированы к моменту выполнения её команды.
    • Однако возможны Non-Repeatable Read и Phantom Read.
  3. Repeatable Read (Повторяемое чтение):

    • Гарантирует, что данные, которые вы читаете, останутся неизменными во время транзакции.
    • Предотвращает грязное чтение и неповторяющееся чтение.
    • Однако фантомные строки все ещё возможны.
  4. Serializable (Сериализуемый):

    • Гарантирует, что транзакции выполняются так, как если бы они выполнялись последовательно, одна за другой.
    • Предотвращает все три проблемы: грязное чтение, неповторяющееся чтение и фантомные строки.
    • Самый строгий — и самый медленный — уровень изоляции.

Почему изоляция транзакций важна?

Теперь представьте базу данных интернет-магазина, в котором тысяча пользователей пытаются одновременно оформить заказ. Без грамотно настроенного уровня изоляции можно столкнуться с огромным количеством конфликтов: от "пропавших" товаров до дублирующихся заказов.

Выбор нужного уровня изоляции помогает справляться с конкурентным выполнением транзакций, обеспечивая баланс между производительностью и целостностью данных. Например:

  • В системах аналитики чаще выбирают минимальные уровни изоляции (например, Read Committed), так как точность данных не всегда критична.
  • В финансовых системах предпочтителен уровень Serializable, чтобы избежать ошибок в расчётах или дублирования операций.

Примеры применения уровней изоляции

  1. Read Committed

Этот уровень обеспечивает, что вы никогда не прочитаете данные, которые могли быть откатаны.

SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
BEGIN;

-- Прочитать данные счета.
SELECT balance FROM accounts WHERE account_id = 1;

-- Если другая транзакция обновит баланс, эти данные немедленно обновятся.
UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;

COMMIT;
  1. Repeatable Read

Этот уровень гарантирует, что если вы читаете данные, они останутся неизменными для вас на протяжении транзакции.

SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
BEGIN;

-- Прочитать данные счета.
SELECT balance FROM accounts WHERE account_id = 1;

-- Даже если другая транзакция обновит этот баланс, вы не увидите изменения.
UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;

COMMIT;
  1. Serializable

В этом уровне транзакция работает так, как если бы она была единственной в системе.

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN;

-- Прочитать данные счёта.
SELECT balance FROM accounts WHERE account_id = 1;

-- Любая другая транзакция, пытающаяся изменить эти данные, будет заблокирована до завершения вашей транзакции.
UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;

COMMIT;

Как выбрать уровень изоляции?

Выбор уровня изоляции зависит от ваших требований:

  • Если скорость важнее точности, и вы готовы терпеть фантомные строки — выбирайте Read Committed.
  • Если точность важна, но вы все еще хотите сохранить высокую производительность — используйте Repeatable Read.
  • Если вам нужна 100% гарантия корректности данных, даже в ущерб скорости — вам подходит Serializable.

Будьте осторожны! Строгие уровни изоляции могут привести к блокировкам и снижению производительности системы. Разумное решение — компромисс между производительностью и согласованностью данных.

2
Задача
SQL SELF, 39 уровень, 4 лекция
Недоступна
Установите уровень изоляции для транзакции
Установите уровень изоляции для транзакции
1
Опрос
Введение в транзакции, 39 уровень, 4 лекция
Недоступен
Введение в транзакции
Введение в транзакции
Комментарии (2)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Денис Уровень 46
20 февраля 2026
Почему про READ UNCOMMITTED ничего не рассказано?
Ra Уровень 2 Student
11 августа 2025
Почему именно "SERIALIZABLE"? Название SERIALIZABLE происходит от слова "serial" (последовательный). Оно описывает ключевое гарантированное свойство: Результат параллельного выполнения транзакций должен быть эквивалентен какому-то последовательному (serial) выполнению этих же транзакций. Другими словами, система должна вести себя так, как если бы транзакции выполнялись строго одна за другой (даже если на самом деле они выполнялись параллельно). Это гарантирует, что: Нет аномалий (грязное чтение, неповторяемое чтение, фантомы). Результат предсказуем, как в однопоточном режиме. Важные нюансы Производительность: SERIALIZABLE требует больше ресурсов, чем другие уровни изоляции (например, READ COMMITTED). False positives: Некоторые СУБД (как PostgreSQL) могут откатывать транзакции, даже если реального конфликта нет (перестраховываются). Не означает "полная блокировка": Современные СУБД добиваются сериализуемости без полной последовательности (через MVCC, предикатные блокировки и т.д.).