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

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

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

Выясняем причину конфликта: почему в файловой базе всё работает, а в SQL — нет?

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

Когда мы пытаемся загрузить такую базу через файл выгрузки .dt в PostgreSQL, сервер СУБД при создании индексов обнаруживает дублирующиеся ключи в поле _idrref (первичный ключ таблицы) и блокирует операцию записи. Ошибка вида _reference99_pkey уже существует прямо указывает на то, что в таблице справочника (в данном примере с внутренним номером 99) есть две и более записи с одинаковым уникальным идентификатором.

Шаг 1. Идентификация объекта метаданных

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

Запустим файловую базу в режиме «Предприятие» и воспользуемся консолью запросов или создадим небольшую обработку, в которой выполним следующий код:


СтруктураХранения = ПолучитьСтруктуруХраненияБазыДанных();
Для Каждого Таблица Из СтруктураХранения Цикл
    Если Таблица.ИмяТаблицыХранения = "_Reference99" Тогда
        Сообщить("Конфликтный объект: " + Таблица.ИмяТаблицы);
        Прервать;
    КонецЕсли;
КонецЦикла;

Зная имя объекта (например, Справочник.Сотрудники), мы сможем прицельно искать дубликаты именно в нем.

Шаг 2. Физическое исправление файла базы данных (ChDBFL.exe)

Прежде чем использовать стандартное Тестирование и исправление (ТиИ), крайне важно выполнить проверку утилитой ChDBFL.exe. Она находится в каталоге установки платформы (папка bin). В отличие от ТиИ, эта утилита работает на низком уровне файловой структуры.

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

  1. Создадим резервную копию файла 1Cv8.1CD.
  2. Запустим ChDBFL.exe.
  3. Укажем путь к файлу базы и установим флаг «Исправлять обнаруженные ошибки».
  4. Запустим процесс восстановления.

Важный момент: часто именно повреждение индексов в файловой базе приводит к тому, что 1С «видит» записи как разные, хотя их UUID совпадают. ChDBFL.exe пересоберет дерево индексов, что может решить проблему еще до этапа выгрузки.

Шаг 3. Поиск и устранение дублей UUID программным способом

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

Рассмотрим пример кода для поиска дублей в конкретном справочнике:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |   Стр.Ссылка КАК Ссылка,
    |   Стр.Наименование КАК Наименование
    |ИЗ
    |   Справочник.Сотрудники КАК Стр";

Результат = Запрос.Выполнить().Выгрузить();
ТаблицаУИД = Новый ТаблицаЗначений;
ТаблицаУИД.Колонки.Добавить("УИД", Новый ОписаниеТипов("Строка", Новый КвалификаторыСтроки(36)));
ТаблицаУИД.Колонки.Добавить("Ссылка");

Для Каждого Стр Из Результат Цикл
    НоваяСтрока = ТаблицаУИД.Добавить();
    НоваяСтрока.УИД = Строка(Стр.Ссылка.УникальныйИдентификатор());
    НоваяСтрока.Ссылка = Стр.Ссылка;
КонецЦикла;

ТаблицаУИД.Сгруппировать("УИД", "Ссылка"); // Это не сработает для поиска дублей напрямую, используем другой подход:
ТаблицаУИД.Колонки.Добавить("Количество");
ТаблицаУИД.ЗаполнитьЗначения(1, "Количество");

Дубли = ТаблицаУИД.Скопировать();
Дубли.Сгруппировать("УИД", "Количество");
Для Каждого СтрДубль Из Дубли Цикл
    Если СтрДубль.Количество > 1 Тогда
        Сообщить("Найден дубль UUID: " + СтрДубль.УИД);
    КонецЕсли;
КонецЦикла;

При обнаружении таких записей рекомендуется одну из них перезаписать с новым УникальныйИдентификатор(), предварительно перенеся ссылки со старого объекта на новый с помощью обработки «Поиск и замена дублей».

Шаг 4. Правильная настройка Тестирования и исправления (ТиИ)

Многие пользователи совершают ошибку, выбирая режим «Очищать объекты» при обнаружении ошибок ссылочной целостности. Это приводит к тому, что документы «исчезают», а сотрудники «отвязываются» от организаций.

Проанализируем правильный подход к ТиИ:

Шаг 5. Альтернативный метод: Выгрузка и загрузка данных XML

Если перенос через .dt стабильно завершается ошибкой pkey, воспользуемся методом логического переноса данных. Рассмотрим работу с обработкой «Выгрузка и загрузка данных XML»:

Этот метод отличается тем, что он не копирует физические таблицы «как есть», а переносит данные в виде текстовых структур. При загрузке в пустую базу на PostgreSQL платформа заново создает все записи и индексы. Если в XML-файле встретятся объекты с одинаковыми UUID, система либо выдаст ошибку на конкретном объекте, либо (в зависимости от настроек) перезапишет существующий, что позволит избежать конфликта уникальности в СУБД.

Шаг 6. Особенности платформы и PostgreSQL

Важно обратить внимание на версию платформы 1С. В версиях ветки 8.3.16 (в частности 8.3.16.1876) наблюдались специфические баги при работе с индексами в PostgreSQL. Проанализируем рекомендации по стабильным версиям:

Резюме и план действий

Подведем итоги. Чтобы успешно перенести базу на сервер и победить ошибку уникальности данных, выполним следующие шаги:

  1. Проверим файловую базу утилитой ChDBFL.exe с исправлением ошибок.
  2. Определим имя проблемной таблицы через ПолучитьСтруктуруХраненияБазыДанных().
  3. Выполним Тестирование и исправление в режиме создания объектов.
  4. Если ошибка сохраняется — выполним перенос данных через XML в пустую серверную базу.
  5. Убедимся, что используется актуальная и стабильная версия платформы 1С.

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

← На главную