При выполнении обмена данными в распределенной информационной базе (РИБ) администраторы и разработчики могут столкнуться с критическим сбоем при вызове метода ПрочитатьИзменения(). В окне сообщений 1С или журнале регистрации появляется системная ошибка СУБД: «Попытка вставки неуникального значения в уникальный индекс: Microsoft SQL Server Native Client: Невозможно вставить повторяющуюся ключевую строку в объект "dbo.#tt..." с уникальным индексом "idx...". HRESULT=80040E2F, native=2601». Разберем природу этого сбоя, выясним, почему временной таблицы нет в базе данных после падения сеанса, и рассмотрим эффективные методы локализации и устранения проблемы.
В процессе загрузки пакета изменений платформа 1С:Предприятие помещает входящий поток сериализованных данных во временные таблицы Microsoft SQL Server. Эти таблицы создаются в служебной базе tempdb и имеют префикс #tt (например, dbo.#tt42), где числовая часть является динамическим суффиксом текущего сеанса. По этой причине найти такую таблицу вручную после аварийного завершения транзакции невозможно: локальная временная таблица уничтожается сервером СУБД сразу после разрыва или отката контекста выполнения.
Для ускорения сопоставления данных и контроля ссылочной целостности платформа автоматически генерирует уникальный индекс для временной таблицы. Ошибка с системным кодом native=2601 (SQLSTATE=23000) возникает тогда, когда в пределах одного загружаемого пакета или одной транзакции оказываются две или более записи с полностью совпадающим первичным ключом. В зависимости от типа метаданных дублирование может возникнуть в следующих элементах:
Проанализируем типовые ситуации, приводящие к формированию некорректного файла обмена:
ПередЗаписью или ПриЗаписи) разработчик не установил проверку системного флага загрузки, при импорте начинает повторно выполняться прикладная логика. В результате платформа пытается повторно рассчитать или сгенерировать подчиненные данные, что порождает дубли.Вместо полного перебора базы вручную воспользуемся профессиональными инструментами анализа:
EXCP и DBMSSQL. В момент падения обмена журнал зафиксирует точный SQL-запрос к таблице #tt с перечнем системных полей. По именам этих полей с помощью функции ПолучитьСтруктуруХраненияБазыДанных() можно мгновенно определить проблемный регистр или справочник 1С.Exception и коду ошибки 2601. Это позволит перехватить конкретный SQL-батч и значения строк прямо в момент нарушения уникальности индекса.<RecordSet> или <v8:Record>.Рассмотрим порядок действий для восстановления штатной работы распределенной базы данных.
Шаг 1. Локализация проблемных данных методом деления регистрации
Если нет возможности настроить технологический журнал, применим метод изолированной регистрации:
Шаг 2. Устранение коллизии в периодическом регистре
Если выяснилось, что два документа создают одинаковую запись в периодическом регистре сведений с одинаковым периодом, скорректируем время одного из документов либо изменим логику формирования движений, чтобы исключить дублирование измерений.
Шаг 3. Корректировка программного кода
Проверим все подписки на события и модули наборов записей. Любая прикладная генерация движений должна блокироваться при загрузке обмена:
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
// Обязательная проверка флага обмена данными
Если ЭтотОбъект.ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
// Прикладной алгоритм формирования движений
СформироватьСлужебныеДвижения();
КонецПроцедуры
Шаг 4. Программная фильтрация в плане обмена
Для предотвращения аварийной остановки обмена при повторении подобных ситуаций можно добавить программный перехват в модуль плана обмена в обработчик события ПриПолученииДанныхОтГлавного (или ПриПолученииДанныхОтПодчиненного):
Процедура ПриПолученииДанныхОтГлавного(ЭлементДанных, ПолучениеЭлемента, ОтправитьНазад)
// Проверяем тип входящих данных
Если ТипЗнч(ЭлементДанных) = Тип("РегистрСведенийНаборЗаписей.КурсыВалют") Тогда
// При необходимости выполняем валидацию или предварительное чтение
// для предотвращения коллизий уникальности
КонецЕсли;
КонецПроцедуры
Шаг 5. Полный пересчет итогов
В обеих базах (источнике и приемнике) выполним операцию «Тестирование и исправление» с обязательным пунктом «Пересчет итогов» либо выполним полное отключение и повторный расчет итогов через управление итогами в режиме предприятия. Это устранит возможные скрытые рассинхронизации агрегатных таблиц перед повторной отправкой пакета.