Почему возникают конфликты блокировок при параллельном выполнении задач бизнес-процессов?

Программист 1С v8.3 (Обычные формы) 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

При попытке ускорить обработку задач бизнес-процессов путем распараллеливания фоновых заданий разработчики часто сталкиваются с ошибкой «Конфликт блокировок». Рассмотрим, почему это происходит, даже если мы используем управляемые блокировки, и как с этим работать в высоконагруженных системах.

Анализ причин возникновения конфликта

Основная проблема заключается в том, что метод ВыполнитьЗадачу() является атомарным для бизнес-логики, но крайне тяжелым для СУБД. При его вызове происходит не просто запись значений реквизитов, а цепочка сложных системных операций:

  1. Проверка условий маршрутизации и точек перехода.
  2. Создание новых записей в таблицах задач (команда INSERT в БД).
  3. Пересчет индексов, таких как ByProcPointExec, которые критически важны для работы подсистемы бизнес-процессов.

Когда несколько фоновых заданий одновременно выполняют ВыполнитьЗадачу(), СУБД начинает конфликтовать за ресурсы индексов. Даже при использовании БлокировкаДанных, SQL Server может инициировать эскалацию блокировок, превращая блокировку конкретной строки в блокировку всей страницы или даже всей таблицы индекса, что приводит к остановке остальных процессов.

Разбор процесса обработки задач

Давайте проанализируем код, который вызывает ошибку, и поймем, где именно возникает «узкое горлышко».


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

В данном примере, несмотря на явное использование БлокировкаДанных, метод ВыполнитьЗадачу() запускает скрытые механизмы, которые не учитывают наши ручные блокировки. Если выполнение задачи приводит к созданию новой задачи, платформа выполняет вставку в таблицу, что провоцирует конкуренцию за страницы индекса.

Как решить проблему блокировок?

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

1. Разделение записи реквизитов и выполнения задачи

Если логика позволяет, разнесите заполнение данных и само выполнение задачи в разные операции. Заполнение реквизитов — это безопасная операция, которая редко вызывает конкуренцию. Выполнение задачи, которое меняет статус и создает новые записи, лучше выполнять последовательно или малыми порциями.

2. Использование очереди заданий

Вместо того чтобы отдавать весь массив задач на одновременную обработку, реализуйте механизм очереди. Фоновые задания могут работать с общим регистром сведений, в котором статус задачи меняется с «К обработке» на «В обработке». Это позволит контролировать количество активных транзакций, обращающихся к системным таблицам бизнес-процессов.

3. Анализ режима управления блокировками

Проверьте, что в свойствах конфигурации установлен режим «Управляемый». Если у вас режим «Автоматический и управляемый», убедитесь, что все задействованные метаданные (документы, задачи, бизнес-процессы) переведены в явный управляемый режим. Использование даже одного объекта в автоматическом режиме может привести к эскалации блокировок до уровня всей таблицы.

4. Минимизация нагрузки на индексы

Если профайлер показывает конфликт в индексе ByProcPointExec, это прямой сигнал о том, что система «захлебывается» при массовой вставке записей в бизнес-процессы. Попробуйте:

Помните, что платформа 8.3 значительно лучше справляется с многопоточностью, однако механизмы бизнес-процессов по своей архитектуре требуют строгого порядка обработки. Если вы видите, что конфликт происходит на уровне платформенных механизмов, лучший способ — последовательное выполнение тех операций, которые меняют состояние бизнес-процесса.

← На главную