Справочник системных ошибок и решений

Windows Server, Active Directory, 1С:Предприятие, СУБД, Linux, Cisco, MikroTik, Asterisk.

⚠️ Важная информация Все материалы, инструкции, команды и скрипты на сайте предоставлены исключительно в ознакомительных целях. Их применение может повлиять на работу операционной системы, программного обеспечения, баз данных, сетевого оборудования и других компонентов инфраструктуры. Перед выполнением действий создайте резервную копию и по возможности протестируйте изменения в безопасной среде. Пользователь самостоятельно оценивает риски и несет ответственность за результат. При отсутствии необходимых знаний обратитесь к квалифицированному ИТ-специалисту.

1С:Предприятие и СУБД

Зацикливание в 1С: Бесконечно вызывается подписка на событие

Обновлено: 10.09.2026 · Официальная документация ↗

Механика событий и причины рекурсии

Механизм Подписок на события в платформе 1С:Предприятие позволяет исполнять произвольный код в момент возникновения системных событий (например, ПриЗаписи, ОбработкаПроведения). Зацикливание (бесконечная рекурсия) происходит, когда код внутри подписки инициирует действие, которое снова вызывает эту же подписку. В результате стек вызовов переполняется (Stack Overflow), сеанс пользователя зависает (потребляя 100% одного ядра ЦП) или аварийно завершается сервером 1С по тайм-ауту. Бизнес-риски: парализация работы пользователей, блокировка таблиц СУБД из-за незавершенных транзакций (Lock Wait Timeout).

Типовые паттерны зацикливания

Место ошибкиДействие разработчикаРезультат
Подписка ПриЗаписи СправочникаИзменение реквизита самого объекта и вызов Объект.Записать().Вызов Записать() снова генерирует событие ПриЗаписи. Бесконечный цикл.
Перекрестные подписки (Пип-Понг)Запись Документа1 изменяет Документ2. А подписка Документа2 изменяет Документ1.Взаимная рекурсия. Сложно отлаживается.
Обработка проведенияЗапись движений (наборов записей) с вызовом Набор.Записать(Истина), что снова вызывает подписки регистраторов.Переполнение стека вызовов транзакции.

Алгоритм устранения рекурсии в коде 1С

Сценарий 1: Правильная работа с текущим объектом (Источник)

Никогда не вызывайте метод Записать() для объекта (Источник), который передается в процедуры подписок ПередЗаписью или ПриЗаписи. Изменения, внесенные в реквизиты объекта Источник в событии ПередЗаписью, сохранятся в БД автоматически платформой.

// НЕПРАВИЛЬНО: Вызовет рекурсию
Процедура МояПодпискаПередЗаписью(Источник, Отказ)
    Источник.Комментарий = "Изменено программно";
    Источник.Записать(); // ФАТАЛЬНАЯ ОШИБКА
КонецПроцедуры

// ПРАВИЛЬНО:
Процедура МояПодпискаПередЗаписью(Источник, Отказ)
    Источник.Комментарий = "Изменено программно";
    // Платформа сама запишет изменения
КонецПроцедуры

Сценарий 2: Использование маркеров (ДополнительныеСвойства) для разрыва перекрестных вызовов

Если вам нужно программно записать связанный объект, и вы хотите предотвратить срабатывание его подписок, используйте свойство ОбменДанными.Загрузка или передавайте маркер через ДополнительныеСвойства.

// Код, инициирующий запись связанного объекта
СвязанныйОбъект = СсылкаНаОбъект.ПолучитьОбъект();
СвязанныйОбъект.ДополнительныеСвойства.Вставить("ПропуститьМоюПодписку", Истина);
СвязанныйОбъект.Записать();

// Код внутри подписки связанного объекта
Процедура ПодпискаСвязанногоОбъекта(Источник, Отказ)
    Если Источник.ДополнительныеСвойства.Свойство("ПропуститьМоюПодписку") Тогда
        Возврат; // Прерываем выполнение, разрывая цикл
    КонецЕсли;
    
    // Основная логика подписки...
КонецПроцедуры

Типовые ошибки администраторов/программистов

  • Вызов Записать() в событии ПриЗаписи: На этапе ПриЗаписи объект уже сохранен в СУБД (но транзакция еще не зафиксирована). Изменять его свойства поздно. Если требуется дозаписать данные, используйте отложенное выполнение через обработчики ожидания (на клиенте) или фоновые задания, но лучше перенести логику в ПередЗаписью.
  • Игнорирование ОбменДанными.Загрузка: При массовых программных загрузках (из XML/JSON) подписки будут срабатывать на каждый объект, катастрофически замедляя процесс и провоцируя циклы. Устанавливайте Объект.ОбменДанными.Загрузка = Истина и обрабатывайте этот флаг первыми строками в ваших подписках (через Возврат;).
💡 Практика специалистов: Практика ITSTM: При проектировании сложных систем с множеством подписок мы требуем от разработчиков реализовывать 'Защиту от дурака'. На уровне общих модулей вводится глобальный счетчик рекурсии (через параметры сеанса или повторно используемые модули). Если глубина вложенности превышает 5, код принудительно вызывает Исключение, предотвращая зависание rphost.

Частые вопросы (FAQ)

Как найти точку зацикливания, если сервер зависает?

В конфигураторе запустите отладку. В момент зависания нажмите паузу (Прервать отладку). Откройте панель 'Стек вызовов' (Ctrl+Alt+C). Вы увидите длинный список повторяющихся вызовов одних и тех же процедур — это и есть ваша рекурсия.

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

Да. В современных конфигурациях на базе БСП (Библиотека стандартных подсистем) практически все типовые подписки начинаются с проверки флага Источник.ОбменДанными.Загрузка. Если он Истина, типовой код не выполняется.

Можно ли отключить конкретную подписку программно?

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

Почему рекурсия приводит к блокировке базы?

Вызов подписок происходит в рамках транзакции записи объекта в БД. При зацикливании транзакция никогда не завершается (Commit), удерживая эксклюзивные блокировки (X-locks) на таблицах СУБД. Другие пользователи ставятся в очередь и получают Lock Wait Timeout.

Полезные материалы
Рекомендуем