Почему регламентное задание 1С выгружает старые данные и как это исправить?

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

Ситуация, когда код во внешней обработке выдает актуальные остатки, а то же самое регламентное задание (РЗ) выгружает «зависшие» старые данные, — одна из самых коварных в практике разработчика 1С. На первый взгляд кажется, что платформа магическим образом кэширует результат запроса, но на самом деле причины кроются в механизмах работы серверного кластера, особенностях сеансов фоновых заданий и управлении кэшем метаданных. Разберем по шагам, почему это происходит и как победить эту проблему.

Анализируем контекст выполнения: сервер против клиента

Первое, что мы должны осознать: фоновое задание (ФЗ) всегда выполняется на сервере под системной учетной записью (обычно usr1cv8), в то время как внешняя обработка часто запускается в контексте клиента. Разберем основные причины расхождения данных:

  1. Разница в часовых поясах и датах. Если в коде используется функция ТекущаяДата(), она берет время сервера. Если сервер 1С и сервер СУБД находятся в разных часовых поясах или время на сервере 1С сбито, запрос на остатки получит неверный параметр.
  2. Кэширование сеансов в пуле. Платформа 1С не завершает процесс rphost после каждого задания. Сеансы могут использоваться повторно. Если в общем модуле используются переменные модуля (объявленные вне процедур), они могут сохранять свои значения между запусками заданий.
  3. Кэш метаданных (srvinfo). При динамическом обновлении конфигурации сервер может «запомнить» старую структуру запроса или старую версию кода специально для фоновых процессов, чтобы не прерывать их работу.

Проверяем параметры запроса в фоновом задании

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


Процедура ВыгрузитьОстаткиНаСервере() Экспорт
    Запрос = Новый Запрос;
    Запрос.Текст = "ВЫБРАТЬ ... ГДЕ Период = &Период";
    
    // Используем ТекущаяДатаСеанса() вместо ТекущаяДата()
    ПараметрДата = ТекущаяДатаСеанса();
    Запрос.УстановитьПараметр("Период", ПараметрДата);
    
    // Записываем параметры в Журнал Регистрации для контроля
    ЗаписьЖурналаРегистрации("ОтладкаРЗ", УровеньЖурналаРегистрации.Информация, , , 
        "Задание запущено. Параметр Дата: " + ПараметрДата);
    
    // Вывод сообщений, которые можно прочитать через консоль заданий
    ОбщегоНазначенияКлиентСервер.СообщитьПользователю("Текущий период запроса: " + ПараметрДата);
    
    Результат = Запрос.Выполнить();
    // ... дальнейшая логика
КонецПроцедуры

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

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

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

Сделаем задание предопределенным в конфигураторе:

  1. Зайдем в дерево метаданных: Общие -> Регламентные задания.
  2. Найдем наше задание и установим свойство Предопределенное в значение Истина.
  3. В консоли заданий убедимся, что галочка Использование также включена.
  4. Обязательно перезагрузим службу серверного кластера 1С.

Перезагрузка сервера — это радикальный, но эффективный метод. Она принудительно очищает оперативную память рабочих процессов rphost и сбрасывает кэш конфигурации, который находится в папке sncfg внутри каталога srvinfo.

Работа с «Консолью заданий» и очистка старых экземпляров

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

  1. Полностью удалим строку регламентного задания в консоли.
  2. Применим изменения в конфигураторе (если они были).
  3. Создадим задание заново, вручную прописав все параметры.
  4. Если база клиент-серверная, проверим, нет ли «зависших» фоновых процессов в консоли администрирования кластера (mmc-снапшот).

Влияние кэширования планов SQL-запросов

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

Чтобы исключить этот фактор, можно попробовать добавить в текст запроса «шум» — комментарий, который меняется при каждом запуске (например, текущее время запуска):


ТекстЗапроса = "ВЫБРАТЬ ... // " + Строка(Новый УникальныйИдентификатор());
Запрос.Текст = ТекстЗапроса;

Это заставит СУБД каждый раз пересобирать план выполнения запроса, исключая влияние старого кэша планов.

Резюме и рекомендации

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

Соблюдение этих правил позволит вам избежать «мистических» ошибок и обеспечит стабильную выгрузку актуальных данных в автоматическом режиме.

← На главную