Как исправить ошибку дублирования ключей в уникальном индексе _acc2401 в PostgreSQL и корректно выгрузить данные по одной организации?

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

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

23505: ERROR: duplicate key value violates unique constraint "_acc2401_2" DETAIL: Key (_fld2422, _code, _idrref)=(0, 01.01, \x88080015172f0b4011f15a8760a1fe20) already exists.

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

Причины сбоя: почему падает план счетов

Таблица с префиксом _acc в структуре таблиц 1С хранит данные плана счетов, где _code — это код счета (например, «01.01»), а _idrref — его уникальный идентификатор (GUID). Сбой возникает по одной из двух базовых причин:

  1. Рассинхронизация или повреждение B-Tree индексов СУБД. Платформа 1С при любом обращении к плану счетов контролирует наличие предопределенных счетов. Поиск выполняется по индексу СУБД. Если индекс поврежден (вследствие аварийной остановки сервера, миграции данных или различий версий библиотек glibc/локалей), PostgreSQL сообщает платформе, что запись с кодом «01.01» отсутствует. 1С пытается автоматически инициализировать и вставить предопределенный счет заново, на что СУБД реагирует ошибкой нарушения первичного ключа 23505.
  2. Физическое дублирование записи. В процессе создания начального образа РИБ или сбоя транзакции в таблицу записалась строка-дубль с тем же идентификатором. Так как целостность нарушена на уровне СУБД, механизмы 1С не могут даже прочитать таблицу без падения.

Способ 1. Переиндексация на уровне PostgreSQL

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

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

REINDEX TABLE _acc2401;

Для гарантированного устранения возможных расхождений во всей информационной базе рекомендуется запустить полную переиндексацию:

REINDEX DATABASE "имя_вашей_базы";

После завершения процедуры перезапустим службу сервера 1С:Предприятия и проверим открытие плана счетов.

Способ 2. Поиск и удаление физического дубля через SQL

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

Выполним запрос для выявления дублирующихся записей конкретного счета:


SELECT ctid, _fld2422, _code, encode(_idrref, 'hex') 
FROM _acc2401 
WHERE _code = '01.01';

Поле ctid возвращает физический адрес строки на диске. Если запрос вернул две одинаковые записи с совпадающим идентификатором, удалим ошибочный дубль по его адресу ctid:


DELETE FROM _acc2401 
WHERE ctid = '(номер_страницы,номер_строки)';

Сразу после ручного удаления дубля обязательно заново перестроим индекс:

REINDEX TABLE _acc2401;

Способ 3. Пересоздание таблиц через файл .dt

Проверенный и безопасный способ избавиться от внутренних искажений таблиц после некорректного развертывания РИБ — полное пересоздание табличной структуры базы:

  1. Выгрузим информационную базу в файл выгрузки .dt средствами конфигуратора.
  2. Создадим на сервере PostgreSQL новую пустую базу данных с корректными параметрами кодировки и локали.
  3. Загрузим полученный файл .dt в новую базу.

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

Способ 4. Сброс предопределенных данных и отвязка от РИБ

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

1cv8.exe DESIGNER /IBConnectionString "..." /ResetPredefinedData

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

ПланыОбмена.УстановитьГлавныйУзел(Неопределено);

Как правильно разделить базу по одной организации без РИБ

Выгрузка через механизм РИБ часто создает избыточные проблемы со связями и уникальностью. Выясним, почему стандартная обработка ВыгрузкаЗагрузкаДанныхXML не всегда подходит и какие существуют альтернативы.

В типовой обработке ВыгрузкаЗагрузкаДанныхXML отсутствует возможность установить один глобальный отбор по реквизиту Организация сразу на всю базу. Отбор настраивается строго индивидуально для каждого объекта метаданных. В комплексной конфигурации настроить сотни документов, справочников и регистров вручную практически невозможно.

Для надежного выделения организации рассмотрим два проверенных на практике сценария:

  1. Метод копии с очисткой (наиболее надежный). Делаем полную копию рабочей информационной базы. В копии помечаем на удаление все организации, кроме нужной. Предварительно программно или вручную снимаем с проведения документы удаляемых компаний, после чего запускаем стандартную обработку Удаление помеченных объектов. Этот метод гарантирует, что план счетов, константы, служебные регистры и сквозная аналитика останутся абсолютно целыми.
  2. Использование универсального обмена с правилами конвертации. С помощью конфигурации Конвертация данных создаются правила выгрузки, в которых отбор по реквизиту Организация объявляется параметром и фильтрует все выгружаемые данные. Выгрузка осуществляется через встроенную или внешнюю обработку Универсальный обмен данными в формате XML.
← На главную