Получить консультацию

GUID в 1С. Устройство, использование, некоторые нюансы

Содержание

Что такое GUID и где он используется в 1С

GUID расшифровывается как Globally Unique Identifier, и представляет собой статистически уникальный 128-битный идентификатор. Вероятность того, что где-нибудь в мире будут независимо сгенерированы два идентичных ключа, исчезающе мала, так как общее количество возможных ключей составляет 2 в 128 степени. В 1С GUID используется в ссылочных типах данных, а также уникальный идентификатор присваивается каждому вновь образуемому типу данных при добавлении метаданных конфигурации. На примере метаданных обработки: GUID есть у самого объекта метаданных, у объекта данных, и у менеджера этой обработки. Эти идентификаторы используются в механизмах сериализации, а также в механизмах сравнения-объединения конфигураций.
Получить идентификатор у ссылочного объекта можно, а вот программного доступа к GUID метаданных нет – но можно посмотреть идентификаторы образованных типов, выгрузив конфигурацию в файлы, либо получив сериализованное представление нужного объекта.

Устройство GUID в 1С на примерах

Строковое представление GUID – это строка из 32 шестнадцатеричных цифр, состоящая из четырех частей, разделенных дефисами. Уникальные идентификаторы делятся на пять версий. В зависимости от версии GUID, его четыре части формируются по-разному, и содержат разную информацию. Подробное строение GUID описано в спецификации UUID – универсального уникального идентификатора, реализацией которого является GUID.

  1. time-based version. Данная версия содержит информацию о времени генерации GUID и MAC-адресе узла (устройства), на котором идентификатор был сгенерирован
  2. DCE Security version (POSIX UIDs) – также содержит MAC-адрес, но из-за особенностей генерации не подходит в случаях, когда GUID необходимо генерировать чаще чем раз в 7 минут
  3. name-based version (MD5 hashing) – GUID генерируется путем хэширования идентификатора пространства имен и имени. Хэширование производится по алгоритму MD5
  4. randomly generated version – случайно генерируемый GUID
  5. name-based version (SHA-1 hashing) – то же что и версия 3, только в качестве алгоритма хэширования используется SHA-1

GUID для объектов ссылочных типов, которые генерируются в момент записи объекта, относятся к time-based версии, а идентификаторы объектов метаданных, типов значений, предопределенных элементов, созданных в конфигураторе, и полученные методом Новый УникальныйИдентификатор() относятся к версии 4 – случайно генерируемые.

Вооружившись этими знаниями, займемся исследованием GUID-ов, которые мы можем получить в 1С. В качестве объектов для опытов создадим обработку РаботаСГУИД и справочник ТестовыйСправочник. В обработке добавим команду, а в серверном обработчике этой команды пропишем следующий код:

&НаСервере
Процедура ПолучитьСериализованноеПредставлениеНаСервере()
	МенеджерОбработки = Обработки.РаботаСГУИД;
	Сообщить(ЗначениеВСтрокуВнутр(МенеджерОбработки));
	МенеджерОбъектаОбработки = Обработки.РаботаСГУИД.Создать();
	Сообщить(ЗначениеВСтрокуВнутр(МенеджерОбъектаОбработки));
	
	Для Сч = 1 по 3 Цикл
		Эл = Справочники.ТестовыйСправочник.СоздатьЭлемент();
		Эл.Записать();
		Сообщить(Эл.Ссылка.УникальныйИдентификатор());
		Эл.Удалить();
	КонецЦикла;	
	
	// У объекта языка "Метаданные" GUID всегда один и тот же - 9fb58eea-17f2-4200-b105-b288d62f4303
	Сообщить(ЗначениеВСтрокуВнутр(Справочники.ТестовыйСправочник.СоздатьЭлемент().Метаданные()));
	Сообщить(ЗначениеВСтрокуВнутр(Метаданные.Обработки.РаботаСГУИД));

КонецПроцедуры

Метод ЗначениеВСтрокуВнутр сериализует объекты языка в строку. В рассматриваемом примере в окно сообщений будут выведены следующие данные:

{“#”,ff798e9f-e182-4a0f-af78-224dbb45de69,
{0}
}
{“#”,609fe03c-dbf8-4f78-835d-178eed7ceb70}
8e1f9db8-4be2-11ed-a101-2c4d5450919d
8e1f9db9-4be2-11ed-a101-2c4d5450919d
8e1f9dba-4be2-11ed-a101-2c4d5450919d
{“#”,9fb58eea-17f2-4200-b105-b288d62f4303}
{“#”,9fb58eea-17f2-4200-b105-b288d62f4303}

Если выгрузить конфигурацию в файлы и открыть файл с обработкой РаботаСГУИД, можно увидеть, что идентификаторы экземпляра обработки и менеджера обработки действительно соответствуют тому, что мы получили в результате сериализации:

GUID объектов метаданных в 1С

Разберем структуру GUID на примере идентификатора, созданного в момент записи элемента справочника:
8e1f9db8-4be2-11ed-a101-2c4d5450919d

GUID записывается по группами шестнадцатеричных чисел по схеме 8-4-4-4-12. В случае, когда используется версия 1 (основанная на времени), значение групп будет следующим:
8e1f9db8-4be2 – отметка времени Timestamp
11ed – первые бита – это версия GUID, в нашем случае 1. Остальные – формируют оставшуюся часть отметки времени
a101 – вариант GUID И Clock Sequence 
2c4d5450919d – MAC-адрес узла (Node)

 

Так все-таки, можно ли упорядочивать по GUID?

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

Сами уникальные идентификаторы в СУБД хранятся в виде двоичных данных Binary (16), и сортируются побитово как бинарные данные. Попытки использовать GUID для упорядочивания по отметке времени – от лукавого. Во-первых, на оси времени в пределах одной секунды документы разных типов в любом случае не будут располагаться хронологически. Во-вторых, документы одного типа также не будут в общем случае, если они заводятся в рамках разных параллельных сеансов. 

Вывод, подкрепленный цитатой Бориса Нуралиева: использовать GUID для хронологического упорядочивания объектов на оси времени в общем случае нельзя!
“Механизм генерации ссылок обеспечивает только их уникальность. Возрастающая последовательность при их генерации не обеспечивается.” (c)

Получить время из GUID

&НаСервереБезКонтекста
Функция ОтметкаВремениГУИД(ГУИД)

    // В спецификации UUID для версии 1 дата содержится в первых трех группах из схемы 8-4-4-4-12
    // Например, рассмотрим GUID 8e1f9db8-4be2-11ed-a101-2c4d5450919d
    // Дата содержится в первых символах, 8e1f9db8-4be2-11ed которые нужно переставить в обратном порядке: 11ed-4be2-8e1f9db8
    Строка16 = Сред(ГУИД, 15, 4) + Сред(ГУИД, 10, 4) + Сред(ГУИД, 1, 8);
    
    // Убираем знаки "-"(дефисы)
    Строка16 = СтрЗаменить(Строка16, "-", "");
    
    // Убираем первый символ, так как по спецификации это - номер версии стандарта.
    Строка15 = Сред(Строка16, 2);
    
    // Получаем 60-битную отметку времени : ed4be28e1f9db8
	// Преобразуем к десятичному числу
    ЧислоСек = 0;
    Для Позиция = 1 По СтрДлина(Строка15) Цикл
        ЧислоСек = ЧислоСек + Найти("123456789abcdef", Сред(Строка15, Позиция, 1))*Pow(16, СтрДлина(Строка15) - Позиция);
    КонецЦикла;
    ЧислоСек = ЧислоСек / 10000000;
    
    // Прибавляем к дате начала Григореанского календаря
    Возврат Дата(1582, 10, 15, 00, 00, 00) + ЧислоСек + СмещениеСтандартногоВремени() + СмещениеЛетнегоВремени();;
    
КонецФункции

Разбор GUID из ссылки

В 1С из ссылки можно получить тип уникального идентификатора (его версию), время и MAC-адрес узла для версии 1.

&НаСервереБезКонтекста
Функция ВерсияГУИД(ГУИД)
    
    // Номер версии содержится в старшем байте седьмого октета
    Версия = Число(Сред(ГУИД, 15, 1));
    СоответствиеВерсий = Новый Соответствие;
	СоответствиеВерсий.Вставить(0, "NIL GUID");
	СоответствиеВерсий.Вставить(1, "Version 1. (Time-based)");
	СоответствиеВерсий.Вставить(2, "DCE Security (POSIX)");
	СоответствиеВерсий.Вставить(3, "Version 3. Name-based (MD5 hashing)");
	СоответствиеВерсий.Вставить(4, "Version 4. Random");
	СоответствиеВерсий.Вставить(5, "Version 5. Name-based (SHA-1 hashing)");
    
    Возврат СоответствиеВерсий.Получить(Версия);
    
КонецФункции
&НаСервереБезКонтекста
Функция УзелГУИД(ГУИД)

    // В маске UUID 8-4-4-4-12 для версии 1 MAC-адрес содержится в последней 12-значной группе.
    Строка12 = Сред(ГУИД, 25);
    
    // Разделим на октеты
    Результат = "";
    Для Позиция = 1 По СтрДлина(Строка12) Цикл
        Если Позиция % 2 = 1 Тогда
            Результат = Результат + " ";
        КонецЕсли;
        Результат = Результат + ВРЕГ(Сред(Строка12,Позиция,1));
    КонецЦикла;
    Результат = СтрЗаменить(СокрЛП(Результат), " ", ":");
    
    Возврат Результат;
    
КонецФункции
&НаКлиенте
Процедура ВывестиИнформациюПоГУИД(Знач ГУИД, Знач СсылкаНаЭлементСправочника)
	
	Сообщить("Ссылка: " + СсылкаНаЭлементСправочника);
	Сообщить("GUID: " + ГУИД);
	Сообщить("Дата создания: " + ОтметкаВремениГУИД(ГУИД));
	Сообщить("Версия: " + ВерсияГУИД(ГУИД));
	Сообщить("MAC-адрес хоста: " + УзелГУИД(ГУИД));
	
КонецПроцедуры

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

Получение GUID в запросе

В версии платформы 8.3.22 планируется реализовать в языке запросов метод УникальныйИдентификатор(СсылкаНаОбъект) для получения GUID непосредственно в результат запроса.
В остальных же случаях стандартное решение – обойти результат запроса и  использовать метод ссылки УникальныйИдентификатор() в цикле.

Как узнать GUID-ы метаданных?

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

Особенности представления GUID в 1С

Ссылка в 1С представляет собой комбинацию номера таблицы в СУБД и уникального идентификатора. Рассмотрим пример:

&НаСервере
Процедура РазобратьСсылкуНовогоНаСервере()
	ТестСсылка = Справочники.ТестовыйСправочник.ПолучитьСсылку(Новый УникальныйИдентификатор());
    ГУИД= ТестСсылка.УникальныйИдентификатор();
	ВывестиИнформациюПоГУИД(ГУИД, ТестСсылка);
КонецПроцедуры
Дата создания: 23.11.2963 20:26:48
Ссылка: <Объект не найден> (166:adc8d3f7c50e35a2460c6676bb9ce99d)
GUID: bb9ce99d-6676-460c-adc8-d3f7c50e35a2
Версия: Version 4. Random
MAC-адрес хоста: D3:F7:C5:0E:35:A2

Обратите внимание, т.к. версия формата 4 – все данные представляют собой случайный набор символов, соответственно, ни даты ни мак-адреса случайный GUID не содержит.

Представление ссылки в 1С  – это UUID, который записан отличным образом от GUID этой же ссылки. Перед идентификатором выводится номер таблицы в СУБД, в нашем случае 166. Из UUID можно восстановить GUID, и наоборот. Для этого следует разделить запись на октеты (последовательности из 4 символов) и выстроить их в нужном порядке.

GUID:

  • 1 – bb9c
  • 2 – e99d
  • 3 – 6676
  • 4 – 460c
  • 5 – adc8
  • 6 – d3f7
  • 7 – c50e
  • 8 – 35a2

UUID ссылки:

  • 5 – adc8
  • 6 – d3f7
  • 7 – c50e
  • 8 – 35a2
  • 4 – 460c
  • 3 – 6676
  • 1 – bb9c
  • 2 – e99d

Оставьте комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

11 + 7 =

К НАЧАЛУ