При работе с крупными конфигурациями, такими как «1С:Комплексная автоматизация» или «1С:ERP», часто возникает задача полной очистки базы от данных конкретной организации. Попытка решить эту задачу «в лоб» простым перебором и удалением объектов часто приводит к тому, что процесс растягивается на дни, а программа выдает бесконечные ошибки блокировок или нарушения бизнес-логики. Рассмотрим, почему это происходит, и разберем по шагам, как построить эффективный алгоритм удаления.
Проанализируем ситуацию, с которой столкнулся автор темы. В его коде было несколько «узких мест», которые превратили процедуру в четырехдневный марафон с кучей ошибок в финале:
ОБЪЕДИНИТЬ ВСЕ: Когда мы пытаемся собрать ссылки на все документы всех видов в один запрос, SQL-сервер тратит колоссальные ресурсы на построение плана выполнения. В сложных конфигурациях сотни видов документов, и такой запрос становится «неподъемным».ОбменДанными.Загрузка = Истина: Это самая критичная ошибка. Без этого флага при вызове метода Записать() или Удалить() платформа запускает все проверки, прописанные в модулях объектов (процедуры ПередЗаписью, ПриЗаписи). Если это регламентированный отчет (например, 4-ФСС), программа проверяет, не помечен ли он как «сданный». Если отчет сдан, типовая логика запрещает его изменять или удалять, выбрасывая исключение.Вместо одного огромного запроса, давайте разберем подход с последовательной обработкой каждого метаданного. Это позволит системе работать с небольшими порциями данных и быстрее освобождать память. Проанализируем, как изменить цикл обхода:
Для каждого Вид Из Метаданные.Документы Цикл
// Проверяем наличие реквизита Организация
Если Вид.Реквизиты.Найти("Организация") = Неопределено Тогда
Продолжить;
КонецЕсли;
ТекстЗапроса = "ВЫБРАТЬ Ссылка ИЗ Документ." + Вид.Имя + " ГДЕ Организация = &Организация";
Запрос = Новый Запрос(ТекстЗапроса);
Запрос.УстановитьПараметр("Организация", СсылкаНаОрганизацию);
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
// Здесь будет логика удаления
КонецЦикла;
КонецЦикла;
Для того чтобы обойти проверки бизнес-логики (например, те самые ошибки при удалении отчетов 4-ФСС), необходимо использовать свойство ОбменДанными.Загрузка. Рассмотрим подробнее: установка этого флага в значение Истина сообщает платформе, что объект записывается в режиме «как есть», и выполнять прикладные проверки не нужно. Это не только избавляет от ошибок, но и в разы ускоряет процесс.
ДокументОбъект = Выборка.Ссылка.ПолучитьОбъект();
ДокументОбъект.ОбменДанными.Загрузка = Истина;
Перед тем как вызвать метод Удалить(), крайне важно очистить движения документа по регистрам. В «Комплексной автоматизации» документ может делать записи в десятки регистров накопления и сведений. Если просто вызвать Удалить(), платформа будет сама искать эти записи и удалять их по одной, что крайне медленно. Выясним причину: ручная очистка наборов записей через Записать() работает быстрее.
Посмотрим на пример правильной последовательности действий:
// 1. Отмена проведения, если документ проведен
Если ДокументОбъект.Проведен Тогда
ДокументОбъект.Записать(РежимЗаписиДокумента.ОтменаПроведения);
КонецЕсли;
// 2. Очистка движений напрямую (опционально, но ускоряет процесс)
Для каждого Набор Из ДокументОбъект.Движения Цикл
Набор.Записывать = Истина;
Набор.Очистить();
Набор.Записать();
КонецЦикла;
// 3. Непосредственное удаление
Попытка
ДокументОбъект.Удалить();
Исключение
Сообщить("Не удалось удалить: " + ИнформацияОбОшибке().Описание);
КонецПопытки;
Чтобы избежать «зависаний» базы и конфликтов блокировок, о которых упоминалось в сообщениях форума, необходимо разделять процесс на порции. Рекомендуется фиксировать транзакцию каждые 100–500 объектов. Это освобождает ресурсы SQL-сервера.
Разберем пример реализации с транзакциями:
Счетчик = 0;
НачатьТранзакцию();
Пока Выборка.Следующий() Цикл
// Логика удаления...
Счетчик = Счетчик + 1;
Если Счетчик % 200 = 0 Тогда
ЗафиксироватьТранзакцию();
НачатьТранзакцию();
КонецЕсли;
КонецЦикла;
Если ТранзакцияАктивна() Тогда
ЗафиксироватьТранзакцию();
КонецЕсли;
Проанализируем ситуацию: если ваша цель — именно физическое удаление, использование метода Удалить() в коде может быть опасным. Это может оставить в базе «битые ссылки» (объекты, которые ссылаются на удаленный документ). В 1С есть более безопасные способы:
Удалить() установите ПометкаУдаления = Истина (также с использованием ОбменДанными.Загрузка = Истина). Затем воспользуйтесь стандартным инструментом «Удаление помеченных объектов». Он работает в многопоточном режиме и гарантирует ссылочную целостность базы.Для успешного и быстрого удаления документов по организации придерживайтесь следующих правил:
ОбменДанными.Загрузка = Истина.Применяя эти методы, вы сократите время обработки с нескольких дней до нескольких часов и избежите ошибок, связанных с бизнес-логикой конфигурации.