Как по номеру сеанса в 1С определить регламентное задание, изменившее данные?

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

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

Связь сеанса, фонового и регламентного заданий

Для начала проанализируем архитектуру выполнения заданий в платформе 1С:Предприятие. Важно четко разделять понятия регламентного задания и фонового задания:

  1. Регламентное задание — это объект метаданных и элемент расписания. У него самого по себе нет постоянного сеанса в информационной базе.
  2. Фоновый процесс — это непосредственный исполняемый поток, который порождается либо планировщиком регламентных заданий по расписанию, либо программно через метод ФоновыеЗадания.Выполнить().
  3. Сеанс создается в момент старта конкретного фонового задания, и ему присваивается уникальный номер. Все действия, выполняемые внутри этого потока (чтение, запись в регистры, проведение документов), происходят в рамках именно этого номера сеанса.

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

Поиск регламентного задания через Журнал регистрации

Если номер сеанса известен из записи о модификации данных, выясним причину и найдем инициатора через штатный Журнал регистрации (ЖР). Рассмотрим этот процесс по шагам:

  1. Откроем Журнал регистрации и установим отбор по известному номеру сеанса.
  2. Снимем остальные фильтры по событиям, чтобы увидеть хронологию сеанса от самого начала.
  3. Найдем самую первую запись в сеансе — системное событие «Фоновое задание. Запуск» (в служебных терминах _$Job$_.Start).
  4. Посмотрим на колонку Метаданные в строке запуска: если фоновое задание было запущено регламентным, платформа явно укажет имя регламентного задания (например, РегламентноеЗадание.ОбновлениеИндексаППД).
  5. Если колонка метаданных пуста или событие запуска отсутствует, значит, фоновое задание было вызвано динамически из пользовательского сеанса или внешнего соединения программным кодом.

Определение задания через встроенный язык

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

Разберем программный поиск по номеру сеанса или временному интервалу с получением связанного регламентного задания:


Отбор = Новый Структура;
// Получаем список фоновых заданий
МассивЗаданий = ФоновыеЗадания.ПолучитьФоновыеЗадания(Отбор);

Для Каждого Задание Из МассивЗаданий Цикл
    // Проверяем соответствие времени работы или анализируем свойства
    УникальныйИдентификаторРЗ = Задание.РегламентноеЗадание;
    
    Если ЗначениеЗаполнено(УникальныйИдентификаторРЗ) Тогда
        РЗ = РегламентныеЗадания.НайтиПоУникальномуИдентификатору(УникальныйИдентификаторРЗ);
        Если РЗ <> Неопределено Тогда
            Сообщить("Фоновое задание: " + Задание.КраткоеОписание + " порождено РЗ: " + РЗ.Синоним);
            Сообщить("Исполняемый метод: " + Задание.ИмяМетода);
        КонецЕсли;
    Иначе
        Сообщить("Задание запущено программно: " + Задание.ИмяМетода);
    КонецЕсли;
КонецЦикла;

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

Важное ограничение: история выполненных заданий в объекте ФоновыеЗадания очищается сервером автоматически (по умолчанию при превышении лимита в 1000 записей или по прошествии суток), поэтому анализировать данные программно нужно сразу после инцидента.

Разделение регламентных заданий по пользователям

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

Для быстрой локализации проблемы выполним следующие действия:

  1. В списке пользователей информационной базы создадим несколько специализированных служебных учетных записей (например, ПользовательРЗ_Загрузка, ПользовательРЗ_Расчет).
  2. Через консоль регламентных заданий или стандартную форму администрирования назначим каждому подозрительному заданию своего уникального пользователя.
  3. Теперь при любой перезаписи регистра в журнале регистрации будет сразу зафиксирован конкретный пользователь, что мгновенно указывает на виновника без необходимости сопоставления номеров сеансов.

Точечный перехват и логирование через модуль набора записей

Если изменения в регистре происходят непредсказуемо, применим гарантированный способ локализации прямо в конфигурации. Добавим логирование стека вызовов в обработчик записи регистра.

Откроем модуль набора записей нужного регистра сведений (или накопления) и добавим в процедуру ПередЗаписью фиксацию стека:


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

КонецПроцедуры

Использование метода ПолучитьСтекВызовов() позволяет сохранить в журнале регистрации цепочку процедур и функций с номерами строк, которые привели к вызову записи. Это дает исчерпывающий ответ на вопрос, какой алгоритм изменил данные, даже если фоновое задание было динамическим или многопоточным.

Отладка фоновых заданий

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

  1. В конфигураторе перейдем в главное меню: Отладка — Подключение...
  2. Нажмем кнопку Настройка автоматического подключения.
  3. Установим флажок Фоновые задания и применим настройки.
  4. Установим точку останова в процедуре ПередЗаписью или ПриЗаписи исследуемого регистра.

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

← На главную