При свертке или генеральной чистке информационных баз 1С разработчики часто сталкиваются с ситуацией, когда попытка удалить узел плана обмена или очистить зарегистрированные изменения вызывает длительное зависание, отрисовку черного окна предупреждения без текста и аварийное завершение работы платформы. Разберем причинно-следственные связи этой проблемы и рассмотрим практические алгоритмы её решения.
Главная причина аварийного завершения программы заключается в исчерпании адресного пространства 32-разрядного процесса 1С (Out of Memory). Для 32-битного клиента платформы в операционной системе Windows выделяется не более 2–3 ГБ виртуальной памяти.
Проанализируем механику выполнения штатных вызовов:
ПланОбменаОбъект.Удалить() или ПланыОбмена.УдалитьРегистрациюИзменений(Узел) без явного указания конкретных объектов пытаются очистить сразу весь массив записей по всем таблицам базы данных в рамках единой монолитной транзакции.УдалениеОбъекта в таблицы изменений для каждой удаляемой записи. Это дополнительно раздувает таблицы обмена.Важно помнить специфику работы файловой СУБД 1С. При удалении строк из таблиц физический размер файла информационной базы .1CD на диске не уменьшается. Платформа лишь маркирует удаленные страницы как свободные для будущей записи данных.
Чтобы физически уменьшить размер файла базы после очистки данных, необходимо выполнить одно из следующих действий:
.dt и последующую загрузку в чистую базу.chdbfl.exe.Рассмотрим основной способ решения проблемы. Вместо очистки узла целиком выполним порционное удаление зарегистрированных изменений в цикле по каждому объекту метаданных, входящему в состав плана обмена.
Разберем пример кода для выполнения этой операции:
Для Каждого ЭлементСостава Из Метаданные.ПланыОбмена.ИмяПланаОбмена.Состав Цикл
ПланыОбмена.УдалитьРегистрациюИзменений(Узел, ЭлементСостава.Метаданные);
КонецЦикла;
Передача конкретного объекта метаданных во второй параметр метода ПланыОбмена.УдалитьРегистрациюИзменений() позволяет платформе завершать транзакции по каждой таблице отдельно. Память не переполняется, и после завершения цикла сам узел плана обмена удаляется методом Узел.ПолучитьОбъект().Удалить() за несколько секунд.
Обратите внимание: предопределенный узел плана обмена (ЭтотУзел) удалить нельзя — удалению подлежат только подчиненные узлы.
Посмотрим на корректный вариант массового удаления документов или справочников. Чтобы процесс удаления не порождал новые записи о зарегистрированных изменениях в таблицах обмена, необходимо задействовать свойство ОбменДанными.Загрузка.
Проанализируем пример кода:
Объект = Ссылка.ПолучитьОбъект();
Объект.ОбменДанными.Загрузка = Истина;
Объект.Удалить();
Флаг Загрузка = Истина отключает подписки на события и механизмы авторегистрации изменений для данного объекта, предотвращая рост таблиц обмена при чистке базы.
Если нет возможности переписывать код очистки, воспользуемся альтернативными инструментами:
1cv8.exe снимает ограничение в 2–3 ГБ оперативной памяти и позволяет обработать монолитную транзакцию без вылета.