При работе с механизмом Истории данных (Data History) в платформе 1С:Предприятие 8.3, многие разработчики сталкиваются с необходимостью анализа низкоуровневых таблиц, таких как _DataHistoryQueue0. Если для ссылочных типов (справочники, документы) значение поля _DataId интуитивно понятно — это уникальный идентификатор объекта (UUID), то для записей регистров сведений ситуация выглядит сложнее. В этой статье мы подробно разберем, каким образом платформа генерирует этот идентификатор для объектов, не имеющих единственной ссылки.
Для начала проанализируем структуру самой таблицы. Поле _DataId имеет тип binary(20). Опытные специалисты по информационной безопасности и системные программисты сразу узнают в этой длине (160 бит) результат работы алгоритма хеширования SHA-1.
Выясним причину выбора именно хеш-функции. В отличие от справочника, запись регистра сведений определяется набором его измерений. Поскольку платформа должна как-то идентифицировать «сущность» записи в истории, чтобы связать разные версии одной и той же строки регистра, ей необходим суррогатный ключ. Именно SHA-1 позволяет создать уникальный отпечаток набора измерений, который будет стабильным при неизменности ключевых полей.
Рассмотрим подробнее процесс формирования бинарного потока, который подается на вход SHA-1. Важно понимать, что малейшее изменение в порядке следования байтов или кодировке приведет к получению совершенно другого хеша. Платформа 1С использует строгий протокол сериализации данных измерений:
_DataId для новых записей может измениться.СправочникСсылка или ДокументСсылка, в поток данных записывается его внутренний 16-байтовый GUID.TypeID (идентификатор типа). Это необходимо, чтобы отличить, например, пустую ссылку на справочник «Контрагенты» от пустой ссылки на справочник «ФизическиеЛица», так как их UUID могут быть идентичны (нулевыми), а типы — разные.Разберем по шагам, как запись попадает в историю:
Во-первых, в момент записи набора записей регистра сведений (если для него включена история данных), платформа анализирует каждую измененную строку. Для каждой строки вычисляется SHA-1 от значений её измерений.
Во-вторых, сформированный хеш записывается в поле _DataId таблицы _DataHistoryQueue (очередь). Вместе с ним записываются сами данные версии в бинарном виде (поле _Data).
В-третьих, когда срабатывает фоновое задание «Обработка очереди истории данных», платформа переносит эти сведения в основные таблицы истории: _DataHistoryData и _DataHistoryVersions. Поле _DataId здесь служит связующим звеном. Оно позволяет сгруппировать все версии изменений конкретной «записи» (уникальной комбинации измерений) в один логический блок истории.
Проанализируем ситуацию, когда нам нужно программно сопоставить запись в регистре и запись в очереди. На стороне SQL Server это могло бы выглядеть примерно так (в упрощенном виде):
-- Псевдокод для понимания логики формирования
SELECT
HASHBYTES('SHA1',
CAST(Dim_UUID AS BINARY(16)) +
CAST(Dim_String AS VARBINARY(MAX)) +
CAST(Dim_Date AS BINARY(8))
) AS Calculated_DataId
FROM
_InfoReg123 -- Таблица вашего регистра
Однако стоит учитывать, что реализовать это чисто средствами SQL крайне сложно из-за специфики хранения дат и строк в 1С. Платформа делает это на уровне своего программного ядра перед отправкой данных в СУБД.
Выясним, есть ли отличия для регистров, подчиненных регистратору. Для таких объектов история данных может работать в разных режимах. Если регистр является частью «второго контура» (Data History для документов), то идентификатор может быть связан с идентификатором самого документа-регистратора. Однако классический механизм DataHistory для независимых регистров всегда опирается на хеш от набора измерений.
Подведем итог: поле _DataId для регистров сведений — это не случайное число и не системный счетчик. Это детерминированный результат функции SHA-1 от конкатенации бинарных представлений всех измерений регистра. Знание этого механизма помогает при решении сложных задач интеграции, восстановлении данных или при анализе производительности механизмов версионирования в крупных информационных системах на базе 1С.