При работе с распределенными информационными базами (РИБ) или сложными схемами обмена данными часто возникает ситуация, когда стандартный механизм авторегистрации начинает работать неэффективно. Особенно остро это проявляется, когда количество узлов в плане обмена превышает несколько десятков. Рассмотрим ситуацию, когда при поступлении данных от одного узла система автоматически регистрирует эти же изменения для всех остальных узлов, создавая колоссальную нагрузку на таблицы регистрации и замедляя выгрузку сообщений.
Разберем стандартное поведение платформы: если в свойстве объекта Авторегистрация установлено значение Разрешить, то любое изменение объекта (даже полученное в ходе обмена) будет помещено в таблицу регистрации для всех узлов, входящих в этот план обмена. В схеме с «базой-посредником» и 60+ розничными точками это приводит к тому, что сообщение, пришедшее от «Точки-1», заставляет систему записывать 59 лишних строк в таблицу _ConfigChngRec. В результате время выгрузки увеличивается в геометрической прогрессии.
Первым и самым важным шагом является изменение настроек метаданных. Проанализируем, как это сделать правильно:
Авторегистрация в значение Запретить.Для программной регистрации изменений используем метод ПланыОбмена.ЗарегистрироватьИзменения(). Важно передавать в него массив конкретных узлов-получателей, а не всю выборку, чтобы избежать повторения проблемы «регистрации для всех».
Выясним причину, по которой подписки на события могут не срабатывать при миграции данных из основной базы в базу-клон. Когда данные загружаются программно (через механизмы обмена), платформа устанавливает свойству ОбменДанных.Загрузка значение Истина. Это отключает стандартные проверки и обработчики, чтобы предотвратить зацикливание и ускорить запись.
Если нам необходимо, чтобы при загрузке данных из «Центра» в «Клон» эти данные тут же регистрировались для «Розницы», мы должны модифицировать код в подписках на события. Типовая проверка выглядит так:
Если ОбменДанных.Загрузка Тогда
Возврат;
КонецЕсли;
Для решения нашей задачи мы должны изменить логику, разрешив регистрацию для конкретного плана обмена даже в режиме загрузки:
Процедура ПриЗаписиОбъектаДляОбмена(Источник, Отказ) Экспорт
// Если это обычная запись пользователем - регистрируем всегда
// Если это загрузка, проверяем, нужно ли нам проталкивать данные дальше
Если Источник.ОбменДанных.Загрузка Тогда
// Специальная логика регистрации для плана обмена "ОбменРозница"
ПланыОбмена.ЗарегистрироватьИзменения(УзлыРозницы, Источник);
Иначе
// Стандартная регистрация
КонецЕсли;
КонецПроцедуры
Посмотрим на выбор события для регистрации. Для гарантированной и корректной регистрации изменений в планах обмена рекомендуется использовать событие ПриЗаписи. В событии ПередЗаписью объект еще не зафиксирован в базе данных физически. Если после этого произойдет ошибка, регистрация может остаться «висеть», ссылаясь на несуществующие данные. Для регистров накопления и сведений регистрация должна происходить именно в момент записи набора записей.
Если ручная регистрация в подписках все равно создает задержки при записи объектов, проанализируем более продвинутые методы:
ДополнительныеСвойства. Это позволит внутри подписки точно определить, откуда пришел объект и для каких именно узлов его нужно зарегистрировать, избегая лишних запросов к базе данных.Таким образом, комбинируя отключение Авторегистрации с грамотной обработкой свойства ОбменДанных.Загрузка в подписках на события ПриЗаписи, можно добиться существенного сокращения времени выгрузки сообщений и стабильной работы обмена с большим количеством розничных точек.