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

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

При администрировании и разработке в среде 1С:Предприятие 8.3 специалисты иногда сталкиваются с аномальным поведением планировщика задач. Типичный сценарий: после обновления платформы или переноса базы данных на другой сервер регламентное задание начинает выполняться параллельно в двух или более сеансах. При этом в стандартном интерфейсе администрирования (например, в консоли регламентных заданий БСП) отображается только одна запись, а в журнале регистрации фиксируются параллельные запуски, зачастую под разными пользователями. Рассмотрим причины возникновения этой проблемы, методы её диагностики и эффективные способы устранения.

Выясняем причины: почему задание запускается дважды и под разными пользователями?

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

Сбой синхронизации происходит по следующим причинам:

  1. Раздвоение записи в таблице СУБД. При обновлении версии платформы или в процессе реструктуризации базы данных СУБД может произойти физическое дублирование записей. При этом в СУБД появляются две строки для одного и того же регламентного задания.
  2. Особенности работы интерфейса БСП. Стандартные консоли регламентных заданий, разработанные на базе Библиотеки стандартных подсистем, получают список заданий через высокоуровневые механизмы платформы. Эти методы часто группируют полученные записи по уникальному идентификатору UUID задания, из-за чего в форме отображается только одна строка. Однако низкоуровневый планировщик кластера серверов 1С считывает физическую таблицу напрямую и запускает каждый найденный поток независимо.
  3. Утеря пользовательского контекста ("фантомный" запуск). Основное задание запускается под учетной записью, которая явно указана в его свойствах. «Фантомный» же дубликат, образовавшийся из-за сбоя индексов, часто теряет связь с конкретным пользователем информационной базы. В этом случае планировщик 1С запускает фоновое задание под системным пользователем по умолчанию (например, DefUser или пустой пользователь), что приводит к созданию документов с неожиданным автором или к странным записям в журнале регистрации.

Дополнительным фактором выступает серверное кэширование. Планировщик кластера серверов 1С кэширует информацию о расписаниях в файлах внутри каталога srvinfo (в частности, в служебных файлах snccntry.db и snccntry.lst). При некорректном обновлении платформы старый кэш может остаться активным, заставляя планировщик инициировать параллельный старт задачи.

Разберем по шагам, как диагностировать и решить эту проблему различными методами.

Метод 1. Удаление и повторное создание регламентного задания (Стандартный способ)

Самый простой и действенный способ, который помогает в большинстве случаев, — это полное удаление элемента планировщика и его последующее добавление. Рассмотрим этот алгоритм подробнее:

  1. Откроем консоль регламентных заданий в режиме «1С:Предприятие» под учетной записью с административными правами.
  2. Найдем проблемное регламентное задание, которое выполняется параллельно.
  3. Выделим его и выполним команду Удалить. При этом платформа выполнит очистку записей в таблице ScheduledJobs, удалив как видимый экземпляр, так и его скрытую "фантомную" копию, связанную тем же метаданным признаком.
  4. Для проверки убедимся, что в запланированное время задание больше не запускается вообще.
  5. Снова откроем консоль, добавим задание вручную, настроим для него расписание и укажем правильного пользователя для выполнения.

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

Метод 2. Программное удаление "фантомных" предопределенных заданий

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


// Определим структуру отбора по имени метаданных нашего регламентного задания
Отбор = Новый Структура("Метаданные", Метаданные.РегламентныеЗадания.ИмяВашегоЗадания);
НайденныеЗадания = РегламентныеЗадания.ПолучитьРегламентныеЗадания(Отбор);

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

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

Метод 3. Сброс кэша планировщика на сервере 1С:Предприятия

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

  1. Остановим службу сервера «1С:Предприятие» (1C:Enterprise 8.3 Server Agent) через утилиту управления службами операционной системы.
  2. Перейдем в каталог расположения служебных файлов сервера. Обычно он находится по пути C:\Program Files\1cv8\srvinfo\ (для ОС Windows) или /home/usr1cv8/.1cv8/ (для ОС Linux).
  3. Найдем папку конкретного кластера (например, reg_1541), а внутри нее — каталог с идентификатором нашей информационной базы.
  4. В каталоге базы найдем и безвозвратно удалим файлы планировщика задач: snccntry.db и snccntry.lst.
  5. Дополнительно очистим папки серверного кэша конфигурации (папки с именами формата snc, ggr и временные файлы).
  6. Запустим службу сервера «1С:Предприятие» заново.

При запуске сервер 1С заново считает актуальные данные из СУБД и сформирует файлы snccntry.db в консистентном состоянии, что исключит дублирование запусков на уровне кэша.

Метод 4. Использование свойства Ключ для защиты от параллельного выполнения

Рассмотрим превентивный метод защиты, который часто применяют разработчики программных решений на платформе 1С. Чтобы гарантировать, что фоновое задание никогда не запустится параллельно во втором экземпляре (даже при возникновении платформенных сбоев или ошибок СУБД), мы можем использовать свойство Ключ (Key) регламентного задания.

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

Мы можем установить это свойство программно при инициализации задания или при его изменении:


Отбор = Новый Структура("Метаданные", Метаданные.РегламентныеЗадания.ИмяВашегоЗадания);
НайденныеЗадания = РегламентныеЗадания.ПолучитьРегламентныеЗадания(Отбор);

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

Использование свойства Ключ — это отличный способ подстраховать критически важные операции (например, проведение документов, закрытие месяца или синхронизацию данных) от повторного и параллельного выполнения, которое может нарушить логику бизнес-процессов.

← На главную