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

Какие есть типы блокировок при проведении?

2.0 Middle🔥 161 комментариев
#Блокировки и транзакции#Стандарты разработки

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

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

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

Какие есть типы блокировок при проведении

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

Зачем нужны блокировки

Представьте сценарий:

  • Два бухгалтера проводят один и тот же документ одновременно
  • Оба читают текущее значение остатка товара (100 шт)
  • Оба уменьшают остаток на количество из документа (50 шт каждый)
  • В итоге остаток становится 50, вместо 0

Блокировки предотвращают такие ситуации.

Типы блокировок в 1С

1. Блокировка объекта перед проведением

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

// Когда пользователь нажимает "Провести"
// 1С автоматически блокирует этот документ
// Другой пользователь не может провести его одновременно

// На уровне системы это выглядит так:
// SELECT FOR UPDATE FROM РегистрСведений WHERE Документ = &ЭтотДокумент

Механизм:

  • При начале проведения объект помечается как заблокированный
  • Другие пользователи не могут провести этот документ
  • После проведения (успешно или с ошибкой) блокировка снимается

2. Блокировка ресурса (Регистры накопления)

Отличается от блокировки объекта. Здесь блокируется не сам документ, а ресурсы, которые он затрагивает.

// Документ: "Отпуск материалов"
// Затрагиваемый ресурс: Остатки товаров по складам

// 1С блокирует строки в регистре, соответствующие:
// Товар = А
// Склад = Основной

// Другой документ, затрагивающий то же самое сочетание,
// будет ждать освобождения блокировки

Пример в коде:

// В обработчике "ПередПроведением"
Процедура ПередПроведением(Отмена, Режим)
    // Здесь может быть явная блокировка ресурсов
    БлокировкаДанных = Новый БлокировкаДанных();
    БлокировкаДанных.Добавить("РегистрНакопления.ОстаткиТоваров");
    БлокировкаДанных.Заблокировать();
КонецПроцедуры

3. Блокировка на уровне БД (SELECT FOR UPDATE)

Это низкоуровневая блокировка на уровне SQL. 1С использует её автоматически при проведении.

-- При проведении 1С выполняет что-то похожее на:
SELECT * FROM "_AccRg" 
WHERE "Document" = '...' 
FOR UPDATE;  -- Эта строка означает блокировку

Особенности:

  • Работает на уровне СУБД (PostgreSQL, SQL Server, 1С)
  • Автоматическая блокировка
  • При завершении транзакции автоматически снимается

4. Блокировка таблиц (Table-level lock)

Реже используется, когда операция затрагивает большой объём данных.

// При массовом переоценивании всех товаров
// 1С может заблокировать всю таблицу РегистрНакопления.ОстаткиТоваров
// Это медленнее, но гарантирует консистентность

Практический пример блокировок

Сценарий: Проведение документа "Приходная накладная"

// Модуль документа
Процедура ПередПроведением(Отмена, Режим)
    // 1С автоматически добавляет блокировку документа
    
    // Явная блокировка ресурсов (регистров)
    БлокировкаДанных = Новый БлокировкаДанных();
    БлокировкаДанных.Добавить("РегистрНакопления.ОстаткиТоваров");
    БлокировкаДанных.Добавить("РегистрСведений.СтоимостьТоваров");
    БлокировкаДанные.Заблокировать();
    
    // Проверка данных
    ПроверитьКоличество();
    ПроверитьЦены();
КонецПроцедуры

Процедура ПриПроведении(Отмена, Режим)
    // Здесь выполняются действия проведения
    ОбновитьОстатки();
    ОбновитьСтоимость();
    
    // После выполнения ВСЕХ операций блокировка снимается
КонецПроцедуры

Процедура ПослеПроведения(Отмена, Режим)
    // Здесь уже нет блокировки
КонецПроцедуры

Объявление блокировок вручную

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

Параметры блокировки

// Можно указать режим ожидания
БлокировкаДанных = Новый БлокировкаДанных();
БлокировкаДанных.Добавить("Справочник.Товары");

// Режим 1: Ждать доступности (по умолчанию)
БлокировкаДанных.Заблокировать();

// Режим 2: С тайм-аутом
Попытка
    БлокировкаДанных.Заблокировать();
Исключение
    // Если не получилось заблокировать за время тайм-аута
    Сообщение("Данные заблокированы другим пользователем");
КонецПопытки

Проблемы и их решение

Проблема 1: Deadlock (взаимная блокировка)

Когда процесс A ждёт ресурс, заблокированный процессом B, а процесс B ждёт ресурс, заблокированный процессом A.

// НЕПРАВИЛЬНО - может привести к deadlock
// Процесс 1
БлокировкаДанных.Добавить("Справочник.Товары");
БлокировкаДанных.Добавить("Справочник.Склады");
БлокировкаДанных.Заблокировать();

// Процесс 2 (одновременно)
БлокировкаДанных.Добавить("Справочник.Склады");
БлокировкаДанных.Добавить("Справочник.Товары");
БлокировкаДанных.Заблокировать(); // DEADLOCK!

// ПРАВИЛЬНО - всегда блокируем в одном порядке
БлокировкаДанных.Добавить("Справочник.Склады"); // Сначала Склады
БлокировкаДанных.Добавить("Справочник.Товары"); // Потом Товары
БлокировкаДанных.Заблокировать();

Проблема 2: Долгая блокировка

Если процесс удерживает блокировку слишком долго, другие пользователи ждут.

// НЕПРАВИЛЬНО - блокировка удерживается долго
БлокировкаДанных = Новый БлокировкаДанных();
БлокировкаДанных.Добавить("РегистрНакопления.Остатки");
БлокировкаДанных.Заблокировать();

Для каждого Товар Из ПолучитьВсеТовары() Цикл
    ОбработатьТовар(Товар); // Долгая операция со схватом блокировки
КонецЦикла;

// ПРАВИЛЬНО - блокировка только для критичной части
Для каждого Товар Из ПолучитьВсеТовары() Цикл
    // Подготовка без блокировки
    Данные = ПодготовитьДанные(Товар);
    
    // Только критичная часть
    БлокировкаДанных = Новый БлокировкаДанных();
    БлокировкаДанных.Добавить("РегистрНакопления.Остатки");
    БлокировкаДанных.Заблокировать();
    
    ОбновитьОстаток(Товар, Данные);
    // Блокировка автоматически снимается
КонецЦикла;

Практические рекомендации

  1. Блокируй только необходимое — не блокируй весь регистр, если можно заблокировать конкретную партию
  2. Минимизируй время блокировки — выполняй все вычисления до блокировки
  3. Единообразный порядок — всегда блокируй ресурсы в одном порядке для предотвращения deadlock'а
  4. Логирование конфликтов — отслеживай, где возникают блокировки
  5. Тестирование нагрузки — проверяй поведение системы при одновременных операциях

Правильное понимание и использование блокировок — это залог стабильной и надёжной работы учётных систем на 1С, особенно в многопользовательской среде.