Как устранить ошибку нарушения уникальности индекса ReferenceHPK при обмене данными в 1С

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

При выполнении обмена данными между информационными базами через «1С:Конвертацию данных 2.1» (КД 2.1) или планы обмена может возникнуть критическая ошибка уровня СУБД Microsoft SQL Server: «Не удается вставить повторяющуюся строку ключа в объект "dbo._Reference..." с уникальным индексом "...HPK"». Ошибка сопровождается native-кодом 2601 и SQLSTATE=23000.

Разберем природу возникновения этой ошибки, выясним, почему платформа пытается выполнить вставку существующей записи вместо её обновления, и рассмотрим безопасные способы устранения конфликта.

Причины возникновения ошибки

Проанализируем структуру таблиц справочников в СУБД. Таблица справочника (например, _Reference73) имеет первичный кластерный индекс _Reference73HPK, который строится по полям _IDRRef (внутренний уникальный идентификатор GUID объекта) и признаку разделителя данных. Ошибка означает, что СУБД пытается выполнить операцию INSERT со значением _IDRRef, которое уже физически присутствует в таблице.

Такая ситуация в типовых механизмах обмена (КД 2.1) возникает по следующим причинам:

  1. Сбой в алгоритме поиска объекта в базе-приемнике. В правиле конвертации объекта (ПКО) задан поиск по полям поиска (например, по наименованию или коду). Если объект по этим полям не найден (из-за опечатки, лишних пробелов, невидимых символов или разницы в регистре), механизм обмена считает объект новым. При создании нового объекта обработка обмена вызывает метод УстановитьСсылкуНового(), передавая GUID источника. Когда объект записывается, СУБД пытается выполнить INSERT с этим GUID, но в базе-приемнике запись с таким _IDRRef уже существует, что приводит к нарушению уникальности индекса.
  2. Рассинхронизация предопределенных элементов. В платформе «1С:Предприятие 8.3» предопределенные элементы идентифицируются двумя параметрами: ссылкой _IDRRef и системным именем через поле _PredefinedID. Если в базе-источнике и базе-приемнике предопределенные элементы создавались независимо или привязывались вручную, их GUID могут различаться, что вызывает конфликт при попытке сопоставления.
  3. Кэширование структуры данных сервером 1С. При программном изменении свойства ИмяПредопределенныхДанных изменения фиксируются в базе данных, но серверный кэш метаданных может продолжать хранить старую структуру до перезапуска службы.

Способ 1. Корректировка правил обмена в Конвертации данных

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

  1. Включение поиска по уникальному идентификатору. Откроем конфигурацию «Конвертация данных», перейдем в нужное ПКО (в данном случае для справочника видов использования рабочего времени) и убедимся, что включен флаг «Искать объект по уникальному идентификатору». В этом случае система сначала попытается найти элемент по GUID, и если он найден — выполнит обновление (UPDATE), а не вставку нового элемента.
  2. Явное переопределение ссылки в обработчике «Поля поиска». Если в двух базах предопределенные элементы имеют разные идентификаторы, предотвратим попытку создания нового объекта, жестко указав соответствие в обработчике события ПоляПоиска правила конвертации:

Если СвойстваПоиска.Свойство("Наименование") И СвойстваПоиска.Наименование = "Праздники без повышенной оплаты" Тогда
    СсылкаНаОбъект = Справочники.ВидыИспользованияРабочегоВремени.ПраздникиБезПовышеннойОплаты;
КонецЕсли;

Это заставит механизм обмена сопоставить входящие данные с уже существующим элементом справочника независимо от различий в GUID.

Способ 2. Программная привязка предопределенного элемента и сброс кэша

Если в базе-приемнике элемент справочника был создан пользователем вручную и не связан с метаданными конфигуратора, привяжем его программно через реквизит ИмяПредопределенныхДанных:


Процедура ПривязатьПредопределенныйЭлемент()
    ЭлементСправочника = Объект.ВидыИспользованияРабочегоВремени.ПолучитьОбъект();
    ЭлементСправочника.ИмяПредопределенныхДанных = "ПраздникиБезПовышеннойОплаты";
    Попытка
        ЭлементСправочника.Записать();
        Сообщить("Элемент успешно связан с предопределенным значением метаданных.");
    Исключение
        Сообщить("Ошибка при записи: " + ОписаниеОшибки());
    КонецПопытки;
КонецПроцедуры

Важно: После выполнения данной процедуры обязательно выполним перезапуск службы сервера «1С:Предприятия» (или рабочих процессов кластера), чтобы очистить кэш предопределенных элементов и исключить ошибки адресации в памяти сервера.

Способ 3. Поиск и удаление дублей штатными средствами 1С

Если в базе уже присутствуют две записи (одна предопределенная, а вторая была создана обменом или вручную), не следует удалять строки прямыми запросами к СУБД. Прямой DELETE или TRUNCATE на уровне SQL оставляет битые ссылки в таблицах движений документов и регистрах сведений.

Разберем правильный порядок действий:

  1. Откроем типовую обработку «Поиск и удаление дублей» (раздел «Администрирование» — «Обслуживание» — «Корректировка данных»).
  2. Выберем целевой справочник и укажем критерий сравнения по наименованию.
  3. В качестве оригинала укажем корректный предопределенный элемент конфигурации.
  4. Нажмем кнопку «Удалить дубли». Платформа заменит все ссылки на дублирующий элемент во всех проведенных документах и регистрах, после чего безопасно удалит помеченную запись.

Обслуживание индексов на уровне СУБД

Если ошибки уникальности продолжают проявляться даже при корректных данных, проанализируем состояние физических индексов таблицы. В результате сбоев питания или аварийных остановок кластера индекс СУБД может быть поврежден.

Для восстановления целостности выполним перестроение индекса таблицы в среде SQL Server Management Studio (SSMS):

ALTER INDEX ALL ON dbo._Reference73 REBUILD;

После перестроения индексов рекомендуется провести штатное «Тестирование и исправление информационной базы» в конфигураторе с установленными флагами «Реиндексация таблиц информационной базы» и «Проверка логической целостности».

← На главную