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

Что такое уровень изолированности транзакции в БД?

2.0 Middle🔥 121 комментариев
#Базы данных (SQL)

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

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

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

# Что такое уровень изолированности транзакции в БД?

Уровень изолированности (isolation level) определяет, как транзакции взаимодействуют между собой при одновременном доступе к одним и тем же данным. Это одна из четырёх свойств ACID транзакций.

ACID в транзакциях

  • Atomicity — атомарность (всё или ничего)
  • Consistency — консистентность (данные остаются валидными)
  • Isolation — изолированность (транзакции не мешают друг другу)
  • Durability — долговечность (данные сохраняются)

Проблемы конкурентности без изоляции

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

Транзакция 1:              Транзакция 2:
BEGIN                      BEGIN
UPDATE balance=100         
                           SELECT balance  → читает 100!
ROLLBACK                   (Данные откатились! Прочитала грязные данные)

2. Non-Repeatable Read (неповторяемое чтение)

Транзакция 1:              Транзакция 2:
BEGIN
SELECT balance → 50        BEGIN
                           UPDATE balance=100
                           COMMIT
SELECT balance → 100       (Одна транзакция, разные результаты!)

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

Транзакция 1:              Транзакция 2:
BEGIN
SELECT * FROM users        BEGIN
WHERE age > 18  → 5 rows   INSERT INTO users VALUES (..., age=20)
                           COMMIT
SELECT * FROM users        
WHERE age > 18  → 6 rows   (Новая строка появилась!)

4. Lost Update (потерянное обновление)

Транзакция 1:              Транзакция 2:
SELECT balance → 100       
                           SELECT balance → 100
balance = 100 + 50 = 150
UPDATE balance=150
                           balance = 100 + 30 = 130
                           UPDATE balance=130
Витоге: balance=130        (Обновление T1 потеряно!)

Четыре уровня изолированности (SQL Standard)

1. READ UNCOMMITTED (самый слабый)

Позволяет: грязное чтение

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

BEGIN;
  SELECT * FROM users;  -- Может читать незакоммиченные данные
COMMIT;

Проблемы:

  • Dirty reads ✓
  • Non-repeatable reads ✓
  • Phantom reads ✓
  • Lost updates ✓

Использование: Редко, очень небезопасный

2. READ COMMITTED

Позволяет: только коммиченные данные

SET TRANSACTION ISOLATION LEVEL READ COMMITTED;

BEGIN;
  SELECT * FROM users;  -- Читает только закоммиченные данные
COMMIT;

Проблемы:

  • ✗ Dirty reads
  • ✓ Non-repeatable reads
  • ✓ Phantom reads
  • ✓ Lost updates

Использование: По умолчанию в PostgreSQL, MySQL (InnoDB)

3. REPEATABLE READ

Позволяет: Одна транзакция видит снимок данных

SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;

BEGIN;
  SELECT * FROM users;  -- Снимок в начале транзакции
  -- Другие транзакции не смогут изменить эти строки
  SELECT * FROM users;  -- Тот же результат
COMMIT;

Проблемы:

  • ✗ Dirty reads
  • ✗ Non-repeatable reads
  • ✓ Phantom reads
  • ✗ Lost updates

Использование: По умолчанию в MySQL (InnoDB)

4. SERIALIZABLE (самый строгий)

Позволяет: Транзакции работают как будто последовательно

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;

BEGIN;
  SELECT * FROM users;  -- Полная изоляция
  -- Всё как в однопоточном мире
COMMIT;

Проблемы:

  • ✗ Dirty reads
  • ✗ Non-repeatable reads
  • ✗ Phantom reads
  • ✗ Lost updates

Недостаток: Может сильно снизить производительность

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

УровеньDirty ReadNon-Rep. ReadPhantom ReadПроизводительность
READ UNCOMMITTEDОчень быстро
READ COMMITTEDБыстро
REPEATABLE READСредне
SERIALIZABLEМедленно

Практический пример на PostgreSQL

READ COMMITTED (по умолчанию)

Терминал 1:

BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED;
SELECT balance FROM accounts WHERE id=1;  -- 1000

Терминал 2:

BEGIN TRANSACTION;
UPDATE accounts SET balance=500 WHERE id=1;
COMMIT;

Терминал 1 (после коммита в T2):

SELECT balance FROM accounts WHERE id=1;  -- 500 (изменилось!)
COMMIT;

REPEATABLE READ

Терминал 1:

BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;
SELECT balance FROM accounts WHERE id=1;  -- 1000

Терминал 2:

BEGIN TRANSACTION;
UPDATE accounts SET balance=500 WHERE id=1;
COMMIT;

Терминал 1:

SELECT balance FROM accounts WHERE id=1;  -- 1000 (не изменилось!)
COMMIT;

Использование в Django/Python

Django

from django.db import transaction

# Явное задание уровня изолированности
with transaction.atomic():
    user = User.objects.get(id=1)
    user.balance -= 100
    user.save()

SQLAlchemy

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

engine = create_engine('postgresql://...')
Session = sessionmaker(bind=engine)

# Уровень изолированности (PostgreSQL)
session = Session()
conn = engine.raw_connection()
conn.set_isolation_level(1)  # READ COMMITTED

Psycopg2

import psycopg2

conn = psycopg2.connect('...')
conn.set_isolation_level(
    psycopg2.extensions.ISOLATION_LEVEL_REPEATABLE_READ
)

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

READ COMMITTED

  • Стандартный выбор
  • Большинство случаев
  • Хороший баланс между безопасностью и производительностью

REPEATABLE READ

  • Когда нужна консистентность в одной транзакции
  • Финансовые операции
  • Отчёты, которые не должны меняться внутри расчёта

SERIALIZABLE

  • Очень критичные данные
  • Когда невозможно использовать оптимистичные блокировки
  • Редко в production

Решение проблем конкурентности

1. Оптимистичная блокировка (version field)

class Product(models.Model):
    name = models.CharField(max_length=100)
    version = models.IntegerField(default=1)

# В коде
product = Product.objects.get(id=1)
product.name = 'New Name'
affected = Product.objects.filter(
    id=product.id, version=product.version
).update(name=product.name, version=product.version+1)

if not affected:
    raise ConcurrencyError('Product was updated elsewhere')

2. Пессимистичная блокировка (SELECT FOR UPDATE)

from django.db.models import F

with transaction.atomic():
    product = Product.objects.select_for_update().get(id=1)
    product.name = 'New Name'
    product.save()

Итоги

  • Уровень изолированности — настройка БД, как разные транзакции видят друг друга
  • 4 уровня: READ UNCOMMITTED → READ COMMITTED → REPEATABLE READ → SERIALIZABLE
  • Компромисс: больше изоляции = ниже производительность
  • В 99% случаев используй READ COMMITTED (по умолчанию)
  • Для критичных данных используй REPEATABLE READ или явные блокировки