Как исправить ошибку неуникального значения ссылки в таблице _tmpRCT и ошибку SDBL с кодом 30 в 1С

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

При администрировании и обновлении крупных баз данных на платформе 1С:Предприятие 8 специалисты нередко сталкиваются с коварной системной ошибкой. В процессе проведения Тестирования и Исправления (ТиИ) база данных аварийно завершает работу с сообщением: «Нарушено ограничения PRIMARY KEY. Не удается вставить повторяющийся ключ в объект dbo._tmpRCT». При этом попытка провести некоторые документы (например, больничные листы или ведомости) вызывает сопутствующий сбой: «Ошибка SDBL: Тип поля 30:... несовместим с типом поля Fld...».

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

Связь между ошибками СУБД и SDBL: разбираем причины

Для начала проанализируем симптомы и сопоставим данные из логов СУБД и платформы 1С. В сообщении об ошибке фигурируют два ключевых значения:

  1. Шестнадцатеричное значение ключа в SQL: 0x0000001e.
  2. Десятичный тип поля в ошибке SDBL: Тип поля 30:....

Если перевести шестнадцатеричное число 0x1e в десятичную систему счисления, мы получим ровно 30. Это указывает на то, что обе ошибки вызваны одной и той же фундаментальной проблемой: конфликтом и дублированием внутренних идентификаторов типов объектов метаданных.

Внутри платформы 1С каждому объекту метаданных (справочнику, документу, плану видов характеристик) сопоставляется уникальный целочисленный код (ID типа). Когда платформа выполняет операцию проверки логической и ссылочной целостности в рамках ТИИ, на стороне СУБД временно создается служебная таблица dbo._tmpRCT (Referential Consistency Table — таблица ссылочной согласованности). В эту таблицу выгружаются уникальные ID типов для верификации связей. Первичным ключом этой таблицы является сам идентификатор типа.

Если в базе данных по какой-то причине два разных объекта получили одинаковый внутренний ID (в данном случае 30), СУБД пытается дважды вставить значение 0x0000001e в поле первичного ключа таблицы _tmpRCT, что закономерно вызывает ошибку СУБД PRIMARY KEY constraint violation.

Почему возникает дублирование идентификаторов (Баг платформы)

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

  1. Администратор восстанавливает резервную копию базы данных (файл .bak в MS SQL или дамп PostgreSQL) средствами самой СУБД поверх существующей базы.
  2. После восстановления базы данных не выполняется перезапуск службы кластера 1С:Предприятия (конкретно процесса rmngr).
  3. Процесс rmngr сохраняет в своей оперативной памяти старый кэш счетчиков идентификаторов таблиц для этой базы данных.
  4. Разработчик заходит в Конфигуратор и создает новый объект метаданных (например, новый справочник или документ). Платформа обращается к закэшированному счетчику и выделяет новому объекту очередной ID (например, 30).
  5. Однако в физически восстановленной базе данных под этим идентификатором уже существует другой, ранее созданный объект. В результате в базе данных образуется критическая коллизия: два разных по смыслу объекта имеют один и тот же внутренний ID.

Начиная с версии платформы 8.3.15, этот конфликт отслеживается системой более явно, и при попытке обновить конфигурацию СУБД выдает ошибку: «Ошибка SDBL: Для одного ссылочного кода существует более одной таблицы в базе данных».

---

Методы устранения коллизии метаданных

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

Способ 1: Искусственная реструктуризация конфликтующих объектов

Это наиболее щадящий и простой метод, позволяющий заставить платформу 1С самостоятельно перестроить проблемную таблицу СУБД и присвоить ей новый уникальный код.

Для начала нам необходимо определить, какие именно объекты метаданных используют конфликтующий идентификатор 30. Для этого мы можем воспользоваться программным кодом для анализа структуры хранения данных:


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

Предположим, анализ показал, что код 30 одновременно назначен предопределенному справочнику и новому созданному документу. Для исправления ситуации выполним следующие шаги по шагам:

  1. Откроем базу данных в режиме Конфигуратор.
  2. Найдем один из конфликтующих объектов (лучше выбрать тот, который был создан позже или который можно изменять).
  3. Добавим в этот объект временный реквизит (например, реквизит с именем ВременныйБулево и типом Булево).
  4. Нажмем клавишу F7 для обновления конфигурации базы данных. В процессе обновления платформа принудительно запустит механизм реструктуризации этой таблицы. Понимая, что старый ID занят, или пересчитав актуальную схему, платформа выделит таблице новый свободный уникальный идентификатор.
  5. После успешного обновления вернемся в свойства объекта, удалим временный реквизит ВременныйБулево и повторно обновим конфигурацию (клавиша F7).

Важное примечание: Данный способ не сработает напрямую, если конфликтующим объектом является перечисление (ПеречислениеСсылка), поскольку структура хранения перечислений в СУБД отличается и добавить реквизиты к ним в конфигураторе невозможно.

Способ 2: Использование механизма Распределенных Баз Данных (РИБ)

Создание начального образа РИБ — это мощный системный метод очистки и перегенерации внутренней структуры хранения. При создании подчиненного узла платформа заново формирует всю схему таблиц и распределяет новые идентификаторы «с нуля», полностью исключая дублирование.

Выполним процедуру по шагам:

  1. В конфигурации создадим новый План обмена и установим для него свойство «Распределенная информационная база».
  2. Запустим режим «1С:Предприятие» и создадим элемент этого плана обмена (подчиненный узел).
  3. Вызовем стандартную функцию создания начального образа подчиненного узла РИБ. Платформа сформирует чистую, корректную структуру базы данных (в формате файловой или серверной базы) и перенесет туда данные. В созданной базе коллизия ID будет полностью устранена.
  4. Развернем полученный образ базы данных на сервере СУБД.
  5. Отключим созданную базу от главного узла РИБ, чтобы сделать её полностью самостоятельной рабочей базой. Для этого в новой базе выполним следующий код в модуле или во внешней обработке:

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

После этого базу можно использовать в качестве основной рабочей базы данных.

Способ 3: Использование специализированных обработок

Если база данных имеет огромный объем и создание образа РИБ занимает слишком много времени, можно прибегнуть к исправлению метаданных непосредственно в СУБД с помощью специализированных обработок со специализированных ресурсов (например, Инфостарт).

Подобные обработки выполняют следующие действия под управлением администратора:

  1. Анализируют соответствие имен таблиц СУБД и объектов метаданных через чтение системной таблицы Config.
  2. Находят записи, у которых внутренние коды таблиц дублируются.
  3. Физически переименовывают дублирующуюся таблицу на уровне MS SQL Server / PostgreSQL.
  4. Корректируют метаданные во внутренних бинарных таблицах 1С (таких как Params и Config), прописывая корректный свободный ID для переименованной таблицы.

Внимание! Использование этого метода требует высокой квалификации и понимания внутренней структуры хранения данных 1С на уровне СУБД. Не забудьте сделать резервную копию перед запуском подобных утилит.

Способ 4: Пересоздание «нового» объекта

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

  1. Удалим новый конфликтующий объект из конфигурации в Конфигураторе.
  2. Применим изменения конфигурации базы данных (клавиша F7). При этом соответствующая таблица в СУБД физически удалится, освободив спорный ID 30 для старого объекта.
  3. Обязательно перезапустим службу кластера 1С:Предприятия (или процесс rmngr), чтобы очистить кэш идентификаторов в оперативной памяти сервера приложений.
  4. Снова зайдем в Конфигуратор и добавим объект заново. Платформа выделит ему гарантированно уникальный свободный ID.

Профилактика проблемы в будущем

Чтобы больше никогда не сталкиваться с ошибкой неуникальности ссылок в _tmpRCT и сбоями SDBL, строго придерживайтесь важного правила администрирования: при любом восстановлении базы данных из бэкапа средствами СУБД всегда производите перезапуск службы кластера 1С (сервиса rphost/rmngr). Это гарантирует очистку кэша идентификаторов метаданных и предотвратит появление дублирующих кодов при последующей разработке и обновлении конфигураций.

← На главную