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

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

3.0 Senior🔥 111 комментариев
#Блокировки и транзакции

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

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

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

Ответ

Самый высокий уровень изоляции транзакций — это SERIALIZABLE (Сериализуемость).

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

Стандарт SQL определяет четыре уровня изоляции транзакций, расположенные в порядке возрастания уровня защиты:

УровеньНазваниеНа русскомПроблемы
0READ UNCOMMITTEDЧтение незафиксированных данныхГрязное чтение, неповторяемое чтение, фантомные строки
1READ COMMITTEDЧтение зафиксированных данныхНеповторяемое чтение, фантомные строки
2REPEATABLE READПовторяемое чтениеФантомные строки
3SERIALIZABLEСериализуемостьНет проблем

Уровень SERIALIZABLE (Сериализуемость)

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

Гарантии SERIALIZABLE:

  • ✓ Исключает грязное чтение (dirty read)
  • ✓ Исключает неповторяемое чтение (non-repeatable read)
  • ✓ Исключает фантомные строки (phantom reads)
  • ✓ Полная изоляция между транзакциями
  • ✓ Полная консистентность данных

Различия между уровнями на примере

Сценарий: Два пользователя одновременно работают с таблицей товаров. Товар стоит 100 рублей.

Транзакция 1: Прочитать цену → Увеличить на 10% → Записать Транзакция 2: Прочитать цену → Уменьшить на 5% → Записать

READ UNCOMMITTED (грязное чтение)

// Транзакция 1
НачатьТранзакцию();  // уровень 0
Цена = 100;
Цена = Цена * 1.10;  // 110
Записать(Цена);  // ещё не зафиксировано

// Транзакция 2 может прочитать 110 (незафиксированное значение!)
НачатьТранзакцию();  // уровень 0
ПрочитанноеЗначение = 110;  // грязное чтение
Если Транзакция1_ОтменитьТранзакцию() Тогда
    // Мы работаем с несуществующим значением 110!
КонецЕсли;

READ COMMITTED (неповторяемое чтение)

// Транзакция 1
НачатьТранзакцию();  // уровень 1
Цена_Первое = 100;  // Зафиксированное значение

// В это время Транзакция 2 меняет и фиксирует значение
// Другая транзакция успешно зафиксировала Цена = 95

Цена_Второе = Прочитать();  // 95 (неповторяемое чтение!)

REPEATABLE READ (фантомные строки)

// Транзакция 1
НачатьТранзакцию();  // уровень 2
Количество = Выбрать("ОБИРЫ", Где Цена > 100).Количество();  // 5 товаров

// Транзакция 2 добавляет товар с ценой 150 и фиксирует

Количество = Выбрать("ОБИРЫ", Где Цена > 100).Количество();  // 6 товаров
// Фантомная строка! Мы видим новую строку, которой не было раньше

SERIALIZABLE (полная изоляция)

// Транзакция 1
НачатьТранзакцию();  // уровень 3 - SERIALIZABLE
Цена = 100;
Цена = Цена * 1.10;  // 110

// Транзакция 2 ждёт завершения Транзакции 1
// Только после ЗафиксироватьТранзакцию() Транзакция 1
// Транзакция 2 может начаться

// Результат: данные всегда консистентны

Уровень изоляции в 1С

В 1С:Предприятие по умолчанию используется уровень READ COMMITTED, но в некоторых случаях требуется SERIALIZABLE.

Когда нужен SERIALIZABLE

Финансовые операции — переводы денег ✓ Инвентаризация — учёт товаров ✓ Критические данные — где ошибка недопустима ✓ Конкурирующие операции — несколько пользователей одновременно ✓ Бухгалтерские регистры — где нужна полная консистентность

Цена SERIALIZABLE

Основной недостаток — производительность:

  • Много блокировок (deadlocks)
  • Транзакции ждут друг друга
  • Пропускная способность падает
  • Риск тайм-аутов
// Плохо: много конкурирующих операций
// С SERIALIZABLE система будет очень медленной

Для i = 1 По 1000 Цикл
    НачатьТранзакцию();
    Операция(i);
    ЗафиксироватьТранзакцию();
КонецЦикла;

Оптимальный подход

1. Выбирайте правильный уровень

// Для большинства операций хватает READ COMMITTED
НачатьТранзакцию();  // READ COMMITTED по умолчанию
ОбычнаяОперация();
ЗафиксироватьТранзакцию();

// Для критичных операций требуйте SERIALIZABLE
НачатьТранзакцию();  // или используйте SELECT ... FOR UPDATE
КритичнаяОперация();
ЗафиксироватьТранзакцию();

2. Используйте SELECT FOR UPDATE для критичных данных

// Это блокирует строку до конца транзакции
Запрос = Новый Запрос(
    "ВЫБРАТЬ Цена, Количество 
     ИЗ Справочник.Товары 
     ГДЕ Ссылка = &Ссылка 
     ДЛЯ ОБНОВЛЕНИЯ"
);

3. Минимизируйте размер транзакции

НачатьТранзакцию();
    // Только критичные операции
    ОперацияКритичная1();
    ОперацияКритичная2();
ЗафиксироватьТранзакцию();

// Некритичные операции вне транзакции
ОперацияНекритичная();

Практический пример: SERIALIZABLE для бухучёта

// Проводка документа требует SERIALIZABLE
&НаСервере
Процедура ПроверитьИПровести(Документ)
    НачатьТранзакцию();
    Попытка
        // SERIALIZABLE гарантирует, что никто не изменит
        // регистр бухучёта пока мы не завершим проводку
        
        ТекущееСальдо = ПолучитьСальдо(Счёт);
        НовоеСальдо = ТекущееСальдо + Документ.Сумма;
        
        ЗаписатьВРегистр(Счёт, НовоеСальдо);
        Документ.Проведён = Истина;
        Документ.Записать();
        
        ЗафиксироватьТранзакцию();
    Исключение
        ОтменитьТранзакцию();
        Сообщение = Новый СообщениеПользователю();
        Сообщение.Текст = "Ошибка проводки: " + ОписаниеОшибки();
        Сообщение.Сообщить();
    КонецПопытки;
КонецПроцедуры

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

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