Как очистить регистр «Версии объектов» для удаляемых элементов в 1С без ошибки «Недостаточно памяти»?

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

При подготовке информационной базы 1С к удалению помеченных объектов администраторы и разработчики часто сталкиваются с проблемой: огромный объем накопленных версий объектов в регистре сведений ВерсииОбъектов блокирует стандартное удаление или вызывает критическую ошибку «Недостаточно памяти для получения результата запроса к базе данных». Попытки написать простую обработку очистки «в лоб» часто приводят к зависанию системы. При возникновении проблем со стандартным механизмом можно воспользоваться обработкой удаления помеченных объектов с отбором.

В этой статье мы подробно разберем, почему возникает эта ошибка, проанализируем неоптимальные подходы программирования и реализуем максимально быстрый, безопасный и оптимизированный по памяти алгоритм очистки истории версионирования в среде «1С:Предприятие 8».

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

Рассмотрим типичную ошибку начинающих разработчиков. Проанализируем исходный код, который часто приводит к аварийному завершению работы сервера 1С:


// ПРИМЕР НЕПРАВИЛЬНОГО КОДА
Запись = РегистрыСведений.ВерсииОбъектов.СоздатьНаборЗаписей();
ЗаполнитьЗначенияСвойств(Запись.Отбор, ВыборкаДетальныеЗаписи);
Запись.Прочитать(); // Здесь система зависает и падает по памяти
Если Запись.Выбран() Тогда 
    Запись.Удалить();
КонецЕсли;

В этом фрагменте кроются сразу три критические ошибки:

  1. Чтение избыточных данных через Прочитать(): Метод Прочитать() загружает данные из базы данных в оперативную память сервера приложений 1С. Если вы хотите просто удалить записи, считывать их физическое содержимое в память абсолютно бессмысленно и крайне ресурсоемко.
  2. Неактивный или неполный отбор: Если функция ЗаполнитьЗначенияСвойств() не смогла сопоставить поля (например, из-за несовпадения имен колонок в выборке запроса и измерений регистра), отбор по ключевым измерениям останется пустым. Вызов метода Прочитать() на наборе записей с пустым отбором заставит платформу попытаться загрузить весь регистр сведений (который в реальных базах может весить десятки гигабайт) в оперативную память. Результат — гарантированный вылет по ошибке «Недостаточно памяти».
  3. Запросы внутри цикла (порочная практика): Выполнение отдельных SQL-запросов к регистру по каждому элементу справочника внутри цикла Пока Выборка.Следующий() генерирует колоссальную нагрузку на СУБД из-за постоянных сетевых пакетов и накладных расходов на компиляцию запросов.

Правильный и быстрый способ удаления записей через Набор Записей

Выясним главное правило работы с механизмом наборов записей в 1С: чтобы удалить записи из регистра сведений по определенному измерению, метод Прочитать() использовать нельзя!

Достаточно создать пустой объект типа РегистрСведенийНаборЗаписей, жестко установить отбор по нужному измерению (в нашем случае — по объекту, помеченному на удаление) и сразу вызвать метод Записать(). Платформа самостоятельно сформирует быстрый SQL-запрос DELETE на уровне СУБД, удалив только те строки, которые соответствуют установленному отбору. При этом в память сервера приложений 1С не будет загружено ни единого килобайта лишних данных.

Рассмотрим правильный шаблон кода для удаления записей по конкретной ссылке:


НаборЗаписей = РегистрыСведений.ВерсииОбъектов.СоздатьНаборЗаписей();
// Устанавливаем отбор по ведущему измерению "Объект"
НаборЗаписей.Отбор.Объект.Установить(СсылкаНаОбъект);
// Записываем пустой набор (замещение включено по умолчанию)
НаборЗаписей.Записать(Истина); 

Обратите внимание: так как измерение Объект является главным (ведущим) для этого регистра, устанавливать отбор по остальным измерениям (например, по измерению НомерВерсии) не требуется. Платформа автоматически очистит все версии, привязанные к данному объекту.

Пошаговый алгоритм оптимизации массовой очистки

Теперь объединим наши знания и напишем готовую высокопроизводительную процедуру для пакетной очистки регистра сведений. Чтобы избежать другой проблемы — долгой транзакции при очистке огромного объема данных — мы будем обрабатывать данные порциями (пакетами) и выполнять фиксацию транзакций частями. Это не заблокирует работу других пользователей в базе данных. При работе с базами 1С:ERP для аналогичных задач по сокращению объема накопленной информации используется многопоточная свёртка 1С:ERP с параллельной очисткой регистров.

Разберем по шагам создание оптимального алгоритма массового удаления версий объектов:


&НаСервере
Процедура ОчиститьВерсииПомеченныхНаУдалениеНаСервере()
    
    // Шаг 1. Выбираем ссылки объектов, помеченных на удаление, у которых есть версии в регистре
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ РАЗЛИЧНЫЕ
        |   ВерсииОбъектов.Объект КАК ОбъектСсылка
        |ИЗ
        |   РегистрСведений.ВерсииОбъектов КАК ВерсииОбъектов
        |ГДЕ
        |   ВерсииОбъектов.Объект.ПометкаУдаления = ИСТИНА";
    
    РезультатЗапроса = Запрос.Выполнить();
    
     Если РезультатЗапроса.Пустой() Тогда
        Сообщить("Версий помеченных на удаление объектов не обнаружено.");
        Возврат;
    КонецЕсли;
    
    Выборка = РезультатЗапроса.Выбрать();
    
    КоличествоУдаленных = 0;
    
    // Шаг 2. Обходим выборку и удаляем данные транзакциями по 1000 элементов
    Пока Выборка.Следующий() Цикл
        
        НачатьТранзакцию();
        Попытка
            
            // Удаление версий текущего объекта
            НаборЗаписей = РегистрыСведений.ВерсииОбъектов.СоздатьНаборЗаписей();
            НаборЗаписей.Отбор.Объект.Установить(Выборка.ОбъектСсылка);
            НаборЗаписей.Записать(); // Записываем пустой набор
            
            ЗафиксироватьТранзакцию();
            КоличествоУдаленных = КоличествоУдаленных + 1;
            
        Исключение
            ОтменитьТранзакцию();
            ЗаписьЖурналаРегистрации("ОчисткаВерсий",
                УровеньЖурналаРегистрации.Ошибка,,,
                "Не удалось очистить версии для объекта: " + Выборка.ОбъектСсылка + ". Ошибка: " + ОписаниеОшибки());
        КонецПопытки;
        
        // Информируем пользователя каждые 100 объектов
        Если КоличествоУдаленных % 100 = 0 Тогда
            Сообщить("Обработано объектов: " + КоличествоУдаленных);
        КонецЕсли;
        
    КонецЦикла;
    
    Сообщить("Успешно очищены версии для " + КоличествоУдаленных + " объектов.");
    
КонецПроцедуры

Важные архитектурные нюансы регистра «Версии объектов»

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

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

← На главную