При работе с распределенными информационными базами (РИБ) или универсальными обменами данными мы часто сталкиваемся с ситуацией, когда определенные объекты конфигурации регистрируются для передачи на узел, где они совершенно не нужны — решить эту задачу поможет обработка массовой регистрации изменений для обмена. Это приводит к раздуванию таблиц регистрации изменений (например, dbo._DocumentChngR...), увеличению времени обмена и лишней нагрузке на диск.
В этой статье мы подробно разберем, как грамотно исключить объекты из регистрации, проанализируем риски различных подходов и выберем наиболее оптимальное решение с точки зрения производительности и поддержки.
По умолчанию в планах обмена часто используется механизм авторегистрации. Это удобно для старта, но в промышленных масштабах может стать проблемой. Даже если данные узла нигде не используются, сам факт наличия записи в таблице регистрации потребляет ресурсы. Мы рассмотрим три основных стратегии решения этой задачи, от простых настроек до программного вмешательства.
Самый очевидный способ, который приходит в голову первым — открыть конфигуратор, найти нужный План обмена, перейти в его состав и снять галочку напротив ненужного справочника или документа.
Давайте проанализируем, почему этот способ, несмотря на свою простоту, может быть опасен. Этот вариант обсуждался в начале дискуссии, и справедливо было замечено, что у него есть "подводные камни".
Риски изменения состава плана обмена:
Вывод: Используйте этот метод только в том случае, если вы абсолютно уверены, что данный объект никогда и ни при каких условиях не должен мигрировать ни на один узел данного плана обмена.
Если ваша конфигурация построена на базе Библиотеки Стандартных Подсистем (БСП), для изучения которой существуют удобные справочники с примерами, — а это большинство современных типовых решений (1С:ERP, 1С:УТ, 1С:Бухгалтерия) — у вас есть мощный инструмент: Правила регистрации объектов (ПРО).
Этот метод позволяет настроить логику без изменения кода конфигурации, работая в режиме "Предприятие".
Как это работает:
Отказ = Истина, объект не будет зарегистрирован для обмена.Преимущество этого метода в гибкости. Вы можете настроить сложные условия (например, "не регистрировать документы прошлых периодов" или "не регистрировать помеченные на удаление"). Однако, с точки зрения производительности, платформа все равно инициирует событие проверки правил при каждой записи объекта.
Наиболее производительный и надежный способ — это перехват события записи объекта и принудительная очистка списка получателей обмена. Это позволяет точечно управлять регистрацией для конкретных условий.
Мы будем использовать подписку на событие ПередЗаписью. Для реализации этого подхода лучше всего использовать механизм Расширений конфигурации, который позволяет гибко дорабатывать систему, не снимая основную конфигурацию с поддержки — для этого подойдёт расширение для отключения регистрации объектов в EnterpriseData. Сама работа с расширениями становится проще при использовании специальных утилит, таких как обработка для группового управления расширениями или инструменты для анализа изменений и потенциальных конфликтов.
У любого ссылочного объекта (Справочник, Документ) есть свойство ОбменДанными. Оно содержит коллекцию Получатели. Если эта коллекция пуста, регистрация в таблицы изменений не производится.
Давайте рассмотрим пример кода, который необходимо поместить в подписку на событие ПередЗаписью для нужных объектов.
Вариант А: Полная блокировка автозаполнения
Самый быстрый способ. Если установить свойство АвтоЗаполнение в значение Ложь, платформа даже не будет пытаться определить, нужно ли регистрировать объект согласно настройкам метаданных.
Процедура ПередЗаписьюДокумента(Источник, Отказ, РежимЗаписи, РежимПроведения)
// Если это загрузка данных из другого узла, то прерываем выполнение,
// чтобы не зациклить обмен или не сломать логику загрузки.
Если Источник.ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
// Полностью отключаем механику определения получателей платформой
Источник.ОбменДанными.Получатели.АвтоЗаполнение = Ложь;
// На всякий случай очищаем коллекцию, если туда что-то попало ранее
Источник.ОбменДанными.Получатели.Очистить();
КонецПроцедуры
Вариант Б: Выборочное удаление получателя
Если вам нужно, чтобы объект уходил на узел "Бухгалтерия", но не регистрировался для узла "Мобильное приложение", код нужно немного усложнить. Мы оставляем АвтоЗаполнение = Истина (по умолчанию), но вручную удаляем конкретный узел из коллекции получателей.
Процедура ПередЗаписьюСправочника(Источник, Отказ)
Если Источник.ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
// Находим ссылку на узел, для которого хотим запретить регистрацию
// В реальном коде лучше использовать кэширование или параметры сеанса,
// чтобы не искать узел запросом при каждой записи.
НежелательныйУзел = ПланыОбмена.МобильноеПриложение.НайтиПоКоду("Mob01");
// Удаляем конкретный узел из списка получателей
Источник.ОбменДанными.Получатели.Удалить(НежелательныйУзел);
КонецПроцедуры
В обсуждении часто забывают, что регистрация происходит не только при записи или изменении, но и при удалении объекта. Если вы настроили логику только в событии ПередЗаписью, то при удалении элемента справочника в таблицу изменений все равно попадет запись (типа DeleteObject).
Чтобы полностью исключить узел из обмена, необходимо создать аналогичную подписку на событие ПередУдалением и прописать там ту же логику очистки получателей.
Процедура ПередУдалениемОбъекта(Источник, Отказ)
Если Источник.ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
// Также отключаем регистрацию факта удаления
Источник.ОбменДанными.Получатели.АвтоЗаполнение = Ложь;
Источник.ОбменДанными.Получатели.Очистить();
КонецПроцедуры
Иногда встречается предложение (вариант 3 из обсуждения) оставить регистрацию как есть, но создать регламентное задание, которое раз в сутки будет чистить таблицы изменений запросом или методом УдалитьРегистрациюИзменений.
Давайте разберем, почему это плохая практика:
_ChangeR могут оставаться большими по занимаемому месту на диске, даже если они пустые (эффект "дырок" в файле БД).Для исключения объектов из регистрации на узлах наиболее правильным подходом является комбинация методов:
ПередЗаписью и ПередУдалением для нужных типов объектов. В коде подписки устанавливайте Источник.ОбменДанными.Получатели.АвтоЗаполнение = Ложь.