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