При выполнении тяжелых операций, таких как групповое перепроведение большого массива документов или загрузка данных за прошлые периоды, программисты часто сталкиваются с системной ошибкой: «Объект, удерживающий менеджер временных таблиц, помещен в кэш или образовал циклическую ссылку». Эта проблема особенно характерна для платформы 1С:Предприятие 8.3 (в частности, веток 8.3.14 и выше) и типовых конфигураций вроде Бухгалтерия предприятия 3.0.
В этой статье мы подробно разберем, почему возникает эта ошибка, как она связана с механизмами платформы и какие практические шаги помогут ее устранить.
Для начала проанализируем ситуацию с технической точки зрения. Менеджер временных таблиц (МенеджерВременныхТаблиц) — это объект, который неразрывно связан с текущим сеансом и конкретным соединением с базой данных в СУБД. Платформа 1С накладывает жесткое ограничение: этот объект не может быть сериализован (преобразован в последовательность байтов). Это означает, что его нельзя передать между серверными вызовами как параметр, нельзя сохранить в реквизит формы и нельзя поместить в кэш (например, в повторно используемые значения или временное хранилище).
Ошибка возникает в двух основных случаях:
Структура или Массив), которая содержит ссылку на объект Запрос, а этот запрос, в свою очередь, держит ссылку на МенеджерВременныхТаблиц. Если эта структура где-то «зависает» в памяти или ссылается сама на себя, сборщик мусора не может ее удалить.Рассмотрим подробнее пути решения проблемы.
Самый надежный способ борьбы с этой ошибкой — явное управление жизненным циклом менеджера временных таблиц. Мы не должны полагаться на то, что платформа сама очистит память. Проанализируем код, в котором происходит перепроведение или запрос. После того как временные таблицы больше не нужны, их необходимо закрыть.
Рассмотрим пример правильной организации кода в цикле обработки документов:
Для каждого ДокументСсылка Из СписокДокументов Цикл
МенеджерВТ = Новый МенеджерВременныхТаблиц;
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = МенеджерВТ;
Запрос.Текст = "ВЫБРАТЬ ... ПОМЕСТИТЬ ВТ_Данные ...";
// Выполняем логику проведения
Попытка
Запрос.Выполнить();
// ... дальнейшая работа ...
Исключение
ЗаписьЖурналаРегистрации("Ошибка проведения", УровеньЖурналаРегистрации.Ошибка,,, ОписаниеОшибки());
КонецПопытки;
// КРИТИЧЕСКИ ВАЖНЫЙ БЛОК:
// Очищаем менеджер, чтобы он не ушел в следующую итерацию или кэш
МенеджерВТ.Закрыть();
Запрос.МенеджерВременныхТаблиц = Неопределено;
МенеджерВТ = Неопределено;
КонецЦикла;
Установка значения Неопределено для переменной и вызов метода Закрыть() гарантируют, что связь между объектами будет разорвана, и менеджер не «потянет» за собой другие структуры данных.
Часто в 1С:Бухгалтерия 3.0 ошибка проявляется на конкретных документах, в которых есть логические ошибки (отсутствие договора, незаполненная аналитика, нехватка остатков). В типовом коде проведения могут существовать участки, где при возникновении исключения (ошибки проведения) объект МенеджерВременныхТаблиц не успевает корректно уничтожиться и «зависает» в памяти рабочего процесса rphost.
Выясним причину через анализ данных:
Если вы используете стандартную обработку «Групповое перепроведение документов», попробуйте следующие настройки:
Посмотрим на кусок кода из типовой функции ЗапуститьПерепроведениеДокументов. Здесь параметры передаются в фоновое задание через структуру:
ПараметрыПерепроведения = Обработки.ГрупповоеПерепроведениеДокументов.ПараметрыПерепроведения();
ПараметрыПерепроведения.Организация = Объект.Организация;
ПараметрыПерепроведения.МоментНачала = Новый МоментВремени(ДатаНачалаПерепроведения, Неопределено);
// ...
РезультатПерепроведения = Обработки.ГрупповоеПерепроведениеДокументов.ЗапуститьПерепроведение(ПараметрыПерепроведения);
Если внутри этой процедуры (ЗапуститьПерепроведение) где-то происходит некорректная запись менеджера ВТ в параметры, которые возвращаются на клиент, возникнет обсуждаемая ошибка. В типовых конфигурациях на замке мы не можем изменить этот код, поэтому единственным выходом остается обновление платформы.
Проанализируем техническую среду. Версия 8.3.14.1779 известна некоторыми проблемами с утечками памяти в фоновых заданиях. Ошибка «Объект, удерживающий менеджер...» часто является симптомом внутреннего бага платформы, который был исправлен в более поздних релизах (например, в ветках 8.3.16, 8.3.18 и выше).
Если обновление невозможно, а ошибка повторяется, рекомендуется настроить Технологический журнал (ТЖ). Для этого создайте файл logcfg.xml с отслеживанием события EXCP (исключения):
<log location="C:\Logs\1C" history="24">
<event>
<eq property="Name" value="EXCP"/>
</event>
<property name="all"/>
</log>
После возникновения ошибки в логах ТЖ можно будет найти стек вызова (какой именно общий модуль и какая строка кода вызвали проблему). Это позволит понять, является ли виновником конкретный запрос в коде или это системный сбой платформы при работе с кэшем метаданных.
Для устранения ошибки выполним следующие шаги:
МенеджерВременныхТаблиц и обнуление ссылок на него.Помните, что менеджер временных таблиц — объект «короткого периода жизни». Чем быстрее вы его закроете после использования, тем стабильнее будет работать ваша система.