Как решить проблему с ошибкой Недостаточно памяти при свёртке базы 1С:УПП 1.3?

Программист 1С v8.3 (Обычные формы) Бухгалтерский учет Промышленность, строительство и АПК
← На главную

Свёртка крупных информационных баз конфигурации 1С:Управление производственным предприятием (УПП 1.3) стандартной обработкой СверткаБазы.epf нередко приводит к падению платформы с системной ошибкой «Недостаточно памяти». Ситуация усугубляется, если используется 32-разрядный клиент или 32-разрядный сервер 1С:Предприятие (rphost), где максимальное адресное пространство одного процесса физически ограничено 3,5–4 ГБ независимо от общего объёма оперативной памяти на физическом сервере.

Особенно часто с этой задачей сталкиваются при подготовке копии базы для налоговых аудиторов или проверяющих органов, когда требуется оставить данные за последние 2–3 года и исключить первичные документы за предыдущие 5–7 лет. Проанализируем ключевые причины возникновения ошибки и рассмотрим надежные пошаговые методы подготовки базы без сбоев платформы.

Почему возникает нехватка памяти при стандартной свёртке

Выясним причину сбоя. Типовая обработка свёртки проектировалась без расчёта на многолетние базы объёмом в десятки и сотни гигабайт. При выполнении стандартного сценария платформа перегружает оперативную память по следующим причинам:

  1. Монолитные выборки и транзакции: алгоритмы свёртки пытаются собрать остатки и рассчитать движения по десяткам регистров в рамках одного непрерывного процесса. Память процесса не успевает освобождаться сборщиком мусора, кэш объектов разрастается и упирается в 32-битный лимит.
  2. Построение графа ссылок: перед удалением документов платформа инициирует проверку ссылочной целостности. Для базы объёмом 70 Гб таблица связей между документами, субконто и регистрами просто не помещается в оперативную память.
  3. Срабатывание бизнес-логики: при стандартной записи документов ввода остатков и очистке движений срабатывают подписки на события и код модулей объектов (ПередЗаписью, ПриЗаписи), порождая паразитные вычисления.
  4. Постоянный пересчёт итогов: каждая запись в регистры накопления или бухгалтерии инициирует обновление таблиц итогов, что забивает буферы СУБД и память рабочего процесса 1С.

Решение 1. Разделение свёртки на этапы и создание корректировок

Разберем рабочий сценарий, который позволяет обойти ошибку переполнения памяти без модификации системных библиотек:

  1. Фиксация остатков: с помощью типовой обработки сформируем только документы ввода остатков (документы КорректировкаЗаписейРегистров или специализированные документы ввода остатков) на нужную дату среза, отключив шаг удаления первичных документов.
  2. Сдвиг даты остатков: переносим созданные документы остатков на границу среза — например, на 23:59:59 дня, предшествующего началу проверяемого периода.
  3. Очистка первичных документов отдельным порционным механизмом: удаление документов выполняем специализированной обработкой небольшими порциями, исключая монолитный поиск ссылок.

Для ускорения записи документов остатков и отключения фоновых проверок обязательно используем признак ОбменДанными.Загрузка = Истина. Посмотрим на пример кода формирования движений:


ДокументОстатков = Документы.КорректировкаЗаписейРегистров.СоздатьДокумент();
ДокументОстатков.Дата = ДатаСреза;
ДокументОстатков.Комментарий = "Ввод начальных остатков под проверку";
ДокументОстатков.ОбменДанными.Загрузка = Истина;
ДокументОстатков.Записать();

Решение 2. Создание «оболочек» документов вместо физического удаления

В конфигурации 1С:УПП 1.3 полное физическое удаление документов за 5–7 лет практически невозможно без повреждения аналитики: документы прошлых лет остаются в закрытых субконто, взаиморасчетах по договорам, регистрах НДС и партионного учёта. Попытка принудительно удалить их через ссылочный контроль вызывает лавину ошибок.

Оптимальный путь для проверяющих — оставить так называемые «оболочки» документов, полностью очистив их финансовую начинку:

  1. Снять старые документы с проведения (или установить Проведен = Ложь).
  2. Очистить наборы записей по всем связанным регистрам.
  3. Очистить табличные части с перечнем номенклатуры, сумм и цен.

Такой подход не ломает ссылочную целостность базы, не требует построения огромных таблиц зависимостей в ОЗУ и отрабатывает в разы быстрее полного удаления. Разберем пример процедуры для пакетной очистки движений:


Выборка = Документы.РеализацияТоваровУслуг.Выбрать(Дата("20100101"), ДатаСреза);
Пока Выборка.Следующий() Цикл
    ОбъектДок = Выборка.ПолучитьОбъект();
    ОбъектДок.ОбменДанными.Загрузка = Истина;
    
    // Очищаем движения по регистрам
    Для Каждого Движение Из ОбъектДок.Движения Цикл
        Движение.Прочитать();
        Если Движение.Количество() > 0 Тогда
            Движение.Очистить();
            Движение.ОбменДанными.Загрузка = Истина;
            Движение.Записать();
        КонецЕсли;
    КонецЦикла;
    
    // Снимаем признак проведения и очищаем табличную часть
    ОбъектДок.Проведен = Ложь;
    ОбъектДок.Товары.Очистить();
    ОбъектДок.Услуги.Очистить();
    ОбъектДок.Записать(РежимЗаписиДокумента.Запись);
КонецЦикла;

Решение 3. Пакетное прямое удаление без проверки ссылок

Если цель заключается именно в физическом удалении объектов из базы (чтобы проверяющие не видели даже заголовков документов), типовую обработку применять нельзя. Выполним порционное удаление напрямую через платформенный метод УдалитьОбъекты() с отключенным флагом проверки ссылок.

Рассмотрим правила, которые предотвратят падение процесса по памяти:

  1. Размер пакета: обрабатываем ссылки порциями по 500–1000 элементов.
  2. Явные транзакции: каждый пакет оборачиваем в явную транзакцию и сразу вызываем ЗафиксироватьТранзакцию(), сбрасывая кэш.
  3. Отключение итогов: перед массивным удалением отключаем пересчёт итогов регистров, а после завершения — пересчитываем их заново.

Посмотрим на пример пакетного удаления ссылок:


МассивДляУдаления = Новый Массив;
Выборка = Документы.ПоступлениеТоваровУслуг.Выбрать(Дата("20100101"), ДатаСреза);

Пока Выборка.Следующий() Цикл
    МассивДляУдаления.Добавить(Выборка.Ссылка);
    
    Если МассивДляУдаления.Количество() >= 1000 Тогда
        НачатьТранзакцию();
        // Второй параметр Ложь отключает ресурсоемкий поиск ссылок
        УдалитьОбъекты(МассивДляУдаления, Ложь);
        ЗафиксироватьТранзакцию();
        
        МассивДляУдаления.Очистить();
    КонецЕсли;
КонецЦикла;

Если МассивДляУдаления.Количество() > 0 Тогда
    НачатьТранзакцию();
    УдалитьОбъекты(МассивДляУдаления, Ложь);
    ЗафиксироватьТранзакцию();
    МассивДляУдаления.Очистить();
КонецЕсли;

Рекомендации по управлению итогами регистров

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


// Отключение итогов перед процедурой
РегистрыНакопления.ВзаиморасчетыСКонтрагентами.УстановитьИспользованиеИтогов(Ложь);
РегистрыБухгалтерии.Хозрасчетный.УстановитьИспользованиеИтогов(Ложь);

// ... выполнение операций ввода остатков и очистки ...

// Включение итогов после завершения
РегистрыНакопления.ВзаиморасчетыСКонтрагентами.УстановитьИспользованиеИтогов(Истина);
РегистрыБухгалтерии.Хозрасчетный.УстановитьИспользованиеИтогов(Истина);
РегистрыБухгалтерии.Хозрасчетный.ПересчитатьИтоги();

После завершения процедур в копии базы обязательно запустите операцию «Тестирование и исправление» в Конфигураторе с обязательной установкой флагов «Реструктуризация таблиц информационной базы» и «Пересчет итогов», а также выполните сжатие базы средствами СУБД (Shrink Database в MS SQL Server), чтобы освободить физическое дисковое пространство.

← На главную