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

Какой самый изолированный уровень изоляции?

2.0 Middle🔥 131 комментариев
#REST API и HTTP

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

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

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

Уровни изоляции транзакций в базах данных

Самый изолированный уровень изоляции — это SERIALIZABLE (Сериализуемость). Это четвёртый и самый строгий уровень из стандартных четырёх уровней изоляции ANSI SQL.

Четыре уровня изоляции

  1. READ UNCOMMITTED — минимальная изоляция (грязное чтение разрешено)
  2. READ COMMITTED — средняя изоляция (только коммиченные данные)
  3. REPEATABLE READ — выше среднего (фантомные чтения возможны)
  4. SERIALIZABLE — максимальная изоляция (полная сериализация)

SERIALIZABLE: самый изолированный уровень

SERIALIZABLE гарантирует, что параллельные транзакции выполняются так, как если бы они были выполнены последовательно (сериально) одна за другой. Это полностью исключает все аномалии:

  • ❌ Грязное чтение (dirty read)
  • ❌ Неповторяющееся чтение (non-repeatable read)
  • ❌ Фантомное чтение (phantom read)
  • ❌ Сериализационный конфликт

Как это работает в разных БД

PostgreSQL

import psycopg2
from psycopg2 import extensions

conn = psycopg2.connect('dbname=test')
conn.set_isolation_level(extensions.ISOLATION_LEVEL_SERIALIZABLE)

cur = conn.cursor()
cur.execute('BEGIN ISOLATION LEVEL SERIALIZABLE')

# Транзакция будет сериализуемой
cur.execute('SELECT * FROM accounts WHERE id = 1')
balance = cur.fetchone()[0]
cur.execute('UPDATE accounts SET balance = %s WHERE id = 1', (balance + 100,))

conn.commit()

PostgreSQL использует Serializable Snapshot Isolation (SSI) — освобождает экзаменуемые вычисления, не блокируя таблицы полностью.

MySQL

import mysql.connector

conn = mysql.connector.connect(host='localhost', user='root', password='', database='test')
cur = conn.cursor()

# Установка уровня изоляции
cur.execute('SET TRANSACTION ISOLATION LEVEL SERIALIZABLE')
cur.execute('START TRANSACTION')

# Операции в транзакции
cur.execute('SELECT * FROM accounts WHERE id = 1')
row = cur.fetchone()

cur.execute('UPDATE accounts SET balance = %s WHERE id = 1', (row[1] + 100,))
conn.commit()

MySQL использует блокировки (locking) на строках и таблицах для обеспечения сериализуемости.

Цена SERIALIZABLE

Максимальная изоляция имеет высокую стоимость:

Производительность

READ UNCOMMITTED    — самая быстрая (практически без лока)
READ COMMITTED      — быстрая
REPEATABLE READ     — медленнее (больше блокировок)
SERIALIZABLE        — самая медленная (максимальные блокировки)

Примеры проблем

# Сценарий: две транзакции конкурируют
# Транзакция 1
BEGIN SERIALIZABLE;
SELECT COUNT(*) FROM orders;  -- Результат: 100
INSERT INTO orders VALUES (...);
COMMIT;

# Транзакция 2 (параллельно)
BEGIN SERIALIZABLE;
SELECT COUNT(*) FROM orders;  -- Может заблокироваться, если транзакция 1 не закончена

В PostgreSQL может возникнуть исключение serialization_failure, и транзакцию нужно повторить:

from psycopg2 import extensions

def execute_with_retry(conn, query, max_retries=3):
    for attempt in range(max_retries):
        try:
            cur = conn.cursor()
            cur.execute('BEGIN ISOLATION LEVEL SERIALIZABLE')
            cur.execute(query)
            conn.commit()
            return
        except psycopg2.extensions.TransactionFailedError:
            conn.rollback()
            if attempt == max_retries - 1:
                raise
            continue

Когда использовать SERIALIZABLE

✅ Используй SERIALIZABLE, когда:

  • Финансовые операции (переводы денег)
  • Критичная консистентность данных
  • Сложные операции с множественными таблицами
  • Согласованность важнее производительности

❌ Не используй SERIALIZABLE, когда:

  • Высокая нагрузка на БД
  • Допустимы небольшие противоречия
  • Читаешь аналитику (non-critical data)

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

# Банковский перевод — критичная операция
def transfer_money(from_account_id, to_account_id, amount):
    try:
        cur.execute('BEGIN ISOLATION LEVEL SERIALIZABLE')
        
        # Проверка баланса
        cur.execute('SELECT balance FROM accounts WHERE id = %s FOR UPDATE', (from_account_id,))
        balance = cur.fetchone()[0]
        
        if balance < amount:
            raise ValueError('Недостаточно средств')
        
        # Списание
        cur.execute('UPDATE accounts SET balance = balance - %s WHERE id = %s', 
                   (amount, from_account_id))
        
        # Начисление
        cur.execute('UPDATE accounts SET balance = balance + %s WHERE id = %s',
                   (amount, to_account_id))
        
        conn.commit()
        return True
        
    except Exception as e:
        conn.rollback()
        raise

Вывод

SERIALIZABLE — это максимальная изоляция, исключающая все аномалии. Её используют для критичных операций, где консистентность данных важнее, чем производительность. Цена — блокировки и снижение пропускной способности.