Нередко разработчики и администраторы 1С сталкиваются с ситуацией, когда в регистрах информационной базы неожиданно появляются или модифицируются записи. При анализе журнала регистрации выясняется, что модификация выполнена фоновым заданием, а из конкретных зацепок есть только номер сеанса. Разберем подробно, совпадает ли номер сеанса с регламентным заданием, всегда ли фоновое задание порождено регламентным и как точно выяснить, какой именно программный код вносит изменения.
Для начала проанализируем архитектуру выполнения заданий в платформе 1С:Предприятие. Важно четко разделять понятия регламентного задания и фонового задания:
ФоновыеЗадания.Выполнить().Однако здесь кроется важный нюанс: если одно фоновое задание программно запускает дочерние фоновые потоки, каждое из них получит собственный независимый сеанс с новым номером. Поэтому номер сеанса однозначно принадлежит конкретному исполняемому потоку фонового задания, но само фоновое задание не всегда является регламентным.
Если номер сеанса известен из записи о модификации данных, выясним причину и найдем инициатора через штатный Журнал регистрации (ЖР). Рассмотрим этот процесс по шагам:
_$Job$_.Start).РегламентноеЗадание.ОбновлениеИндексаППД).Если журнал регистрации очищен или не содержит полных данных, обратимся к менеджеру фоновых заданий через встроенный язык. Платформа хранит историю последних запущенных заданий в оперативной памяти сервера кластера.
Разберем программный поиск по номеру сеанса или временному интервалу с получением связанного регламентного задания:
Отбор = Новый Структура;
// Получаем список фоновых заданий
МассивЗаданий = ФоновыеЗадания.ПолучитьФоновыеЗадания(Отбор);
Для Каждого Задание Из МассивЗаданий Цикл
// Проверяем соответствие времени работы или анализируем свойства
УникальныйИдентификаторРЗ = Задание.РегламентноеЗадание;
Если ЗначениеЗаполнено(УникальныйИдентификаторРЗ) Тогда
РЗ = РегламентныеЗадания.НайтиПоУникальномуИдентификатору(УникальныйИдентификаторРЗ);
Если РЗ <> Неопределено Тогда
Сообщить("Фоновое задание: " + Задание.КраткоеОписание + " порождено РЗ: " + РЗ.Синоним);
Сообщить("Исполняемый метод: " + Задание.ИмяМетода);
КонецЕсли;
Иначе
Сообщить("Задание запущено программно: " + Задание.ИмяМетода);
КонецЕсли;
КонецЦикла;
Обратите внимание на свойство ИмяМетода: даже если задание запущено не регламентным заданием, оно покажет точную процедуру общего модуля, которая выполнялась в фоне.
Важное ограничение: история выполненных заданий в объекте ФоновыеЗадания очищается сервером автоматически (по умолчанию при превышении лимита в 1000 записей или по прошествии суток), поэтому анализировать данные программно нужно сразу после инцидента.
Рассмотрим практический прием администрирования, позволяющий безошибочно выявлять источник изменений в будущем. По умолчанию регламентные задания запускаются от имени системного пользователя или пользователя, указанного в общих настройках.
Для быстрой локализации проблемы выполним следующие действия:
ПользовательРЗ_Загрузка, ПользовательРЗ_Расчет).Если изменения в регистре происходят непредсказуемо, применим гарантированный способ локализации прямо в конфигурации. Добавим логирование стека вызовов в обработчик записи регистра.
Откроем модуль набора записей нужного регистра сведений (или накопления) и добавим в процедуру ПередЗаписью фиксацию стека:
Процедура ПередЗаписью(Отказ, Замещение)
// Записываем подробную информацию о контексте изменения данных
Стек = ПолучитьСтекВызовов();
ЗаписьЖурналаРегистрации(
"КонтрольЗаписиРегистра",
УровеньЖурналаРегистрации.Информация,
ЭтотОбъект.Метаданные(),
,
"Стек вызова: " + Символы.ПС + Стек
);
КонецПроцедуры
Использование метода ПолучитьСтекВызовов() позволяет сохранить в журнале регистрации цепочку процедур и функций с номерами строк, которые привели к вызову записи. Это дает исчерпывающий ответ на вопрос, какой алгоритм изменил данные, даже если фоновое задание было динамическим или многопоточным.
Проанализируем еще один удобный инструмент разработчика — отладчик Конфигуратора. Чтобы поймать момент изменения данных в режиме реального времени, настроим автоматическое подключение:
ПередЗаписью или ПриЗаписи исследуемого регистра.При очередном срабатывании фонового процесса отладчик автоматически перехватит управление, отобразит стек вызовов и позволит пошагово проследить весь путь выполнения алгоритма.