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