Как обеспечить видимость объекта в базе 1С для второго фонового задания сразу после его создания?

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

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

Причина возникновения проблемы

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

Решение 1: Организация очереди через Регистр сведений

Вместо попыток запустить фоновое задание «напрямую» сразу после записи, мы рекомендуем использовать классический паттерн «Очередь заданий». Это наиболее надежный способ для стабильной работы, включая облачные решения, такие как 1С:Фреш.

  1. Создайте Регистр сведений с периодичностью или без, который будет выступать в роли очереди.
  2. В процедуре ПриЗаписи (или сразу после ЗафиксироватьТранзакцию в основном коде) создайте запись в этом регистре, передав туда ссылку на объект и статус «К обработке».
  3. Настройте регламентное задание, которое будет работать по расписанию и опрашивать данный регистр.

Этот подход гарантирует целостность данных: второе задание возьмет в работу только тот объект, который гарантированно записан в БД.

Решение 2: Использование Планов обмена для регистрации изменений

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

Рассмотрим логику реализации:


// При записи объекта регистрируем изменения для узла
ПланыОбмена.ИмяВашегоПлана.ЗарегистрироватьИзменения(Узел, Объект.Ссылка);

// Во втором фоновом задании получаем данные через выборку
Выборка = ПланыОбмена.ВыбратьИзменения(Узел, НомерСообщения);
Пока Выборка.Следующий() Цикл
    // Обработка данных
КонецЦикла;

Этот метод эффективнее, чем произвольный Запрос, так как он использует оптимизированные механизмы платформы для отслеживания новых объектов.

Решение 3: Передача данных через параметры (Snapshot-подход)

В ситуациях, когда объект является относительно «легким» (например, содержит немного реквизитов), можно избежать чтения из БД во втором фоновом задании вовсе. Мы можем передать все необходимые данные в качестве параметров при запуске задания.


ПараметрыЗадания = Новый Структура;
ПараметрыЗадания.Вставить(\"Реквизит1\", Объект.Реквизит1);
ПараметрыЗадания.Вставить(\"Данные\", ...);

ФоновыеЗадания.Выполнить(\"МетодВторогоЗадания\", ПараметрыЗадания);

Важное замечание: Этот метод подходит только в том случае, если второму заданию не нужно получать актуальное состояние объекта из БД на момент старта, так как переданные параметры — это «снимок» данных на момент запуска.

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

Анализируя ситуацию, мы видим, что критической ошибкой является запуск фонового задания до завершения транзакции. Разберем правильную последовательность действий:

  1. Открываем транзакцию: НачатьТранзакцию().
  2. Выполняем запись объекта: Объект.Записать().
  3. Фиксируем транзакцию: ЗафиксироватьТранзакцию().
  4. Только после подтверждения фиксации запускаем следующее фоновое задание через метод ФоновыеЗадания.Выполнить().

Если после выполнения этих шагов проблема сохраняется, проанализируйте вложенность ваших транзакций. Часто бывает так, что вы вызываете запись внутри более крупной транзакции (например, в модуле проведения документа), и транзакция не закрывается до самого конца процесса. В таких случаях используйте ПодключитьОбработчикОжидания для отложенного запуска или вышеописанный метод с Регистром сведений, который будет считывать данные уже после полного завершения всех процессов.

Соблюдая данные рекомендации, мы обеспечиваем стабильную и быструю работу многопоточных процессов, исключая ситуации «ненайденных объектов» и нарушения целостности данных.

← На главную