Как изменить GUID уникальный идентификатор объекта в 1С Предприятии

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

В процессе интеграции информационных систем, настройки распределенных баз данных (РИБ) или восстановления синхронизации после сбоев обмена разработчики часто сталкиваются с необходимостью сопоставить или изменить уникальные идентификаторы (GUID/UUID) существующих элементов справочников или документов. Напрямую отредактировать поле УникальныйИдентификатор у уже записанного в базу объекта стандартными средствами платформы невозможно. Это ограничение заложено в архитектуру платформы для обеспечения ссылочной целостности базы данных.

В рамках этой статьи мы подробно разберем, как решить задачу изменения GUID в 1С:Предприятии безопасными методами, проанализируем изящные обходные пути вроде XML-сериализации, изучим архитектурные альтернативы через регистры соответствия обмена, а также детально разберем, почему прямое вмешательство в таблицы СУБД (SQL Update) несет в себе колоссальные риски для стабильности системы.

Рассмотрим по шагам все доступные инструменты и выработаем оптимальную стратегию работы.

Способ 1. Классическое дублирование с методом УстановитьСсылкуНового()

Если нам необходимо физически изменить GUID существующего объекта в базе данных, единственным штатным программным решением является создание нового элемента-копии с целевым идентификатором и последующая замена всех ссылок на него по всей базе данных с последующим удалением старого элемента.

Разберем этот алгоритм на примере справочника Номенклатура:

  1. Создаем новый объект копированием реквизитов исходного элемента.
  2. Генерируем или получаем строковое представление нужного нам GUID.
  3. Формируем объектную ссылку на основе полученного GUID с помощью метода менеджера справочника.
  4. Привязываем созданную ссылку к новому объекту через метод УстановитьСсылкуНового().
  5. Записываем новый объект в базу данных.
  6. Запускаем процедуру поиска и замены дублирующихся ссылок.

Посмотрим на практическую реализацию этого метода на встроенном языке 1С:


// Предположим, у нас есть старый объект, ссылку на который нужно переопределить
СтарыйОбъектСсылка = Справочники.Номенклатура.НайтиПоКоду("00001");

// Проверяем, найден ли исходный элемент
Если ЗначениеЗаполнено(СтарыйОбъектСсылка) Тогда
    
    // Задаем новый GUID, который мы хотим присвоить элементу
    СтрокаНовогоGUID = "12345678-1234-1234-1234-123456789abc";
    НовыйGUID = Новый УникальныйИдентификатор(СтрокаНовогоGUID);
    
    // Формируем будущую ссылку для нового элемента
    НоваяСсылка = Справочники.Номенклатура.ПолучитьСсылка(НовыйGUID);
    
    // Создаем новый объект копированием реквизитов старого
    НовыйОбъект = Справочники.Номенклатура.СоздатьЭлемент();
    ЗаполнитьЗначенияСвойств(НовыйОбъект, СтарыйОбъектСсылка.ПолучитьОбъект(), "Код, Наименование");
    
    // Важно: переносим также и другие реквизиты, если это необходимо
    // Устанавливаем подготовленную ссылку для еще НЕ записанного объекта
    НовыйОбъект.УстановитьСсылкуНового(НоваяСсылка);
    
    Попытка
        НовыйОбъект.Записать();
        Сообщить("Новый элемент успешно записан с GUID: " + Строка(НовыйОбъект.Ссылка.УникальныйИдентификатор()));
    Исключение
        ВызватьИсключение "Не удалось записать новый объект: " + ОписаниеОшибки();
    КонецПопытки;
    
КонецЕсли;

Важное ограничение метода: Функция УстановитьСсылкуНового() работает исключительно для новых, еще ни разу не записанных в базу объектов (у которых свойство ЭтоНовый() возвращает значение Истина). Попытка применить этот метод к уже сохраненному в базе элементу вызовет критическую ошибку платформы.

После создания нового элемента со скопированными реквизитами нам потребуется выполнить замену ссылок. Для этого рекомендуется использовать типовую обработку "Поиск и замена значений" или программно вызвать методы платформы, такие как НайтиСсылки() и произвести замену во всех найденных объектах-метаданных с последующей перезаписью.

Способ 2. Элегантный обходной путь через XML-сериализацию

Ручной перенос реквизитов (особенно у сложных справочников со множеством табличных частей или у документов) — процесс трудоемкий и чреватый ошибками. Мы можем упустить скрытые реквизиты, свойства или дополнительные сведения.

Для создания абсолютно точной копии объекта с новым GUID эффективнее всего использовать механизм XML-сериализации. Суть метода заключается в том, что мы выгружаем объект в текстовый XML-формат, программно заменяем в полученном тексте старый GUID на новый и десериализуем объект обратно. Платформа мгновенно воссоздает полную структуру данных, включая все табличные части.

Проанализируем программный код, реализующий данный подход:


Функция КлонироватьОбъектСНовымGUID(СтарыйОбъектСсылка, СтрокаНовогоGUID) Экспорт
    
    СтарыйОбъект = СтарыйОбъектСсылка.ПолучитьОбъект();
    
    // Сериализуем исходный объект в строку XML
    ЗаписьXML = Новый ЗаписьXML;
    ЗаписьXML.УстановитьСтроку();
    ЗаписатьXML(ЗаписьXML, СтарыйОбъект);
    XMLТекст = ЗаписьXML.Закрыть();
    
    // Получаем строковое представление старого GUID
    СтрокаСтарогоGUID = Строка(СтарыйОбъектСсылка.УникальныйИдентификатор());
    
    // Производим замену старого идентификатора на новый в тексте XML
    МодифицированныйXMLТекст = СтрЗаменить(XMLТекст, СтрокаСтарогоGUID, СтрокаНовогоGUID);
    
    // Десериализуем объект из измененной строки XML
    ЧтениеXML = Новый ЧтениеXML;
    ЧтениеXML.УстановитьСтроку(МодифицированныйXMLТекст);
    
    НовыйОбъект = ПрочитатьXML(ЧтениеXML);
    
    // Принудительно устанавливаем ссылку, так как при чтении XML 
    // объект может инициализироваться как существующий в памяти
    НовыйGUID = Новый УникальныйИдентификатор(СтрокаНовогоGUID);
    НоваяСсылка = Справочники[СтарыйОбъектСсылка.Метаданные().Имя].ПолучитьСсылка(НовыйGUID);
    
    НовыйОбъект.УстановитьСсылкуНового(НоваяСсылка);
    
    Возврат НовыйОбъект;
    
КонецФункции

Использование XML-сериализации значительно снижает риски потери связанных данных внутри объекта при его дублировании и существенно ускоряет разработку универсальных обработок по изменению GUID.

Способ 3. Использование "Регистра соответствия объектов обмена" вместо физической замены

В большинстве случаев необходимость изменения GUID возникает из-за рассинхронизации баз при обмене данными. Вместо того чтобы подвергать базу данных рискам массовой замены ссылок (что может привести к перезаписи документов, пересчету итогов и деградации производительности), правильнее использовать стандартные архитектурные решения платформы 1С.

В конфигурациях, построенных на базе Библиотеки стандартных подсистем (БСП), для этих целей существует специальный Регистр сведений "Соответствие объектов информационных баз". Этот регистр хранит связи между уникальными идентификаторами объектов в разных информационных базах.

Вместо физического изменения GUID в базе-приемнике мы можем просто сделать запись в этот регистр:

При последующих обменах данными (через универсальный формат обмена EnterpriseData или правила конвертации) механизмы БСП будут автоматически сопоставлять эти объекты "на лету", не создавая дублей и избавляя разработчика от необходимости менять системные идентификаторы в транзакционных таблицах.

Почему прямой SQL-апдейт (UPDATE table SET...) — это огромный риск

Иногда у администраторов баз данных возникает соблазн выполнить низкоуровневый запрос к СУБД (например, в MS SQL Server или PostgreSQL), обновив поля идентификаторов напрямую в таблицах. Рассмотрим причины, по которым делать это категорически запрещено на работающих продакшн-базах:

  1. Переворот байт (Endianness / порядок байт): Платформа 1С хранит уникальные идентификаторы в базах данных SQL в бинарных полях типа binary(16) (например, поле _IDRRef для ссылок на объекты или поля реквизитов _Fld...RRef). При этом порядок записи байт в СУБД "перевернут" по особому внутреннему алгоритму 1С по сравнению со строковым представлением UUID в режиме "1С:Предприятие". Обычная запись строки GUID в SQL-поле приведет к физическому повреждению ссылки. Для корректного прямого изменения требуется применять сложные функции побайтового преобразования, что усложняет процесс и увеличивает вероятность ошибки.
  2. Кэширование на сервере приложений 1С: Сервер приложений (процессы rphost) кэширует структуру данных и идентификаторы часто используемых объектов в оперативной памяти. Если изменить GUID непосредственно в SQL-таблице в обход сервера приложений, сервер 1С об этом изменении не узнает. При обращении пользователей к измененному объекту возникнут непредсказуемые сбои блокировок, рассогласование транзакций и критические ошибки "Объект не найден". Потребуется как минимум очистка кэша сервера и перезапуск службы 1С.
  3. Нарушение физической целостности БД: Прямое изменение ключевых индексов таблиц СУБД (таких как кластеризованный индекс по полю _IDRRef) способно разрушить логические связи между таблицами. В результате "поедут" итоги регистров накопления и сведений, нарушится структура подчиненных документов, и база данных может полностью потерять внутреннюю консистентность.

Особенности работы в распределенных информационных базах (РИБ)

Если ваша информационная система функционирует в режиме Распределенной Информационной Базы (РИБ), физическая замена элементов и их GUID требует предельной осторожности.

Создание нового дублирующего элемента и удаление старого неизбежно порождает регистрацию изменений на узлах планов обмена. Эти изменения начнут мигрировать по периферийным базам данных. Если в этот момент в одном из филиалов велась активная работа со старым объектом (например, создавались новые документы с его участием), то при синхронизации возникнет жесткий конфликт автосинхронизации. Это гарантированно приведет к лавинообразному появлению дублей по всей сети или к массовому возникновению битых ссылок вида "Объект не найден", устранять которые в ручном режиме в сотни раз сложнее.

Выводы и рекомендации

Подводя итоги нашего анализа, выделим ключевые правила интерактивного и программного изменения GUID в 1С:

← На главную