Исправление ошибки "Для одного ссылочного кода существует более одной таблицы в базе данных"




Описана методика исправления ошибки путем внесения изменений в sql-таблицы.

Отказ от ответственности: вы все здесь взрослые и делаете всё на свой страх и риск. Да, и ещё: лицензионное соглашение не разрешает вам это делать, поэтому данное описание дано для образовательных целей.

После перехода с 8.3.12 на 8.3.15 словили неприятную ошибку "Для одного ссылочного кода существует более одной таблицы в базе данных". Самое неприятное, что ошибка стала вылезать и на типовых базах, которые никто никогда не трогал.

Гугл ничего не дал кроме стандартных "почистить кэш, перерегистрировать базу в кластере, выполнить ТИИ". Ну и еще "добавить реквизит к объекту и обновить БД" (этот пункт не пробовал, напишите в комментариях — вдруг это самый простой метод в комментариях к этой статье есть сообщение что метод сработал на 8.3.16.1030, пробуйте).

На партнерке есть пара веток, в т.ч. https://partners.v8.1c.ru/forum/topic/1792992, из которой приведу пару цитат:

Воспроизводится так (проверено на релизе 8.3.13.1644 / SQL 2024):
1. Создаём две базы test1 и test2
2. Запускаем конфигуратор test1, добавляем справочник, обновляем конфигурацию. В базе добавляется таблица _Reference21
3. Делаем SQL бэкап базы test1 и восстанавливаем его в test2.
4. Запускаем конфигуратор test2 и добавляем документ, обновляем конфигурацию. В базе видим таблицы: _Reference21 и _Document21.
Помогает перезапуск rmngr.exe после восстановления test2 из бэкапа.

И ответ представителя фирмы 1С:

Да, действительно, в этом сценарии две таблицы получают два одинаковых ссылочных номера.
Это ошибка, будет исправлена в одной из следующих версий.
Что можно сказать по этой ошибке. Во-первых, чистка кэша не поможет. Во-вторых, ошибка воспроизводится только если было хотя бы одно добавление объекта метаданных до восстановления из резервной копии (это приводит к инициализации сервиса в менеджере кластера, и как следствие — сохранению значения последнего номера таблицы).
Рекомендации на сейчас (до выхода версий с исправлением) по обходу ошибки: сразу после восстановления ИБ средствами СУБД — производите перезапуск сервера платформы.

Я провел тест на 8.3.12 — проблема по методике первой цитаты воспроизводится. Так что делаю выводы:
1) проблема с задвоением внутренней нумерации объектов существовала очень давно, как минимум с 8.3.12, но лишь в 8.3.15 добавили проверку (понятно) и запрет применения изменений (а вот тут явно не подумали что у пользователей много таких "поломанных" баз)
2) по-идее, можно жить спокойно на релизах менее 8.3.15 и ждать манны небесной от фирмы 1С.

Ну а нам ждать "одной из следующих версий" нельзя. Базы разработчиков "встают" одна за другой на этой ошибке. Я предлагал откатиться на 8.3.13 или 8.3.14 — но согласился пробовать найти свое решение, т.к. когда будет эта "манна" — неизвестно. А если продолжить использовать "старые" релизы — то дубли нумерации скорее всего будут только плодиться, хоть мы их и не будем видеть.

Размышления привели к пониманию того, что надо найти "где в базе хранится сопоставление таблиц sql и объектов конфигурации". Как оказалось таких мест два: таблица DBSchema и реквизит DBNames таблицы Params.


Попытка получить DBSchema использованием SQL Management studio завершилась неудачей: в режиме ssms получается получить лишь первые 65КБ двоичных данных, хранящихся в таблице, и при вставке в hex-редактор получаем неполную структуру.
А уж DBNames и вовсе хранится в сжатом виде. Поэтому усилия были перенаправлены на поиск инструмента для редактирования этих данных. И он был найден: Восстановление структуры DBSchema
Стоимость инструмента  — 10sm (Мопед не мой!). Впрочем, описанная ниже методика не зависит именно от этой обработки; можете поискать аналог или написать свою. Функционал указанной обработки используется только в части выгрузки DBSchema и DBNames из sql в файл и обратно.

А я опишу методику лечения баз:

  1. рекомендуется использовать Notepad++ или аналог. В отдельном файле открыть текст ошибки из конфигуратора.
  2. запустить обработку, получить DBSchema (схема — список объектов — распознать схему) и DBNames (вверху "загрузить из БД в файл"), выгрузить обе структуры в файлы, указав вверху пути и нажав на кнопки рядом. Открыть файлы в Notepad++. Должно получиться примерно следующее (слева DBNames, справа — DBSchema):
  3. из текста ошибки для каждой пары объектов выбрать "жертву"; проще менять номер у констант или регистров, т.к. на них обычно нет ссылок в реквизитах других объектов. Желательно выбирать в таком качестве "таблицы изменений" вида _ConstChngR2346 или _DocumentChngR3078 не имеющие табличных частей (у нет таблиц вида Document750.VT20237 или _Reference49197_VT3332).
  4. в DBNames находим строку жертвы по номеру объекта, переносим строку в конец файла, меняем номер объекта (+1 к предыдущему)
  5. в файле с текстом ошибки к номеру "жертвы" добавляем "-НовыйНомер"
  6. в DBSchema находим объект, меняем номер объекта (в третьем параметре); ищем все вхождения имени объекта (например Reference3048) — ссылки на этот объект в реквизитах других объектов — выполняем замену например Reference3048 на Reference49189.
  7. в DBNames первый параметр меняем на новый максимальный номер объекта
  8. сохраняем файлы, считываем их обработкой (вся схема — текст — прочитать схему из файла, Имена — Прочитать DBNames из файла), выгружаем из обработки в БД
  9. пишем sql-код для переименования всех таблиц вида:
EXEC sp_rename  _Enum3066, _Enum49200
EXEC sp_rename  _Enum3067, _Enum49201
EXEC sp_rename  _DocumentChngR3078, _DocumentChngR49202

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

EXEC sp_rename '_Reference49197_VT3332._Reference3048_IDRRef', '_Reference49197_IDRRef', 'column'
  1. после выполнения указанных действий также рекомендую удалить-добавить базу в кластере.
    Хотя от представителя 1с на партнерском форуме есть альтернатива — рекомендация перезапускать сервер — в комментариях (7) к данной статье коллега отписался о неэффективности этого метода.

24 Comments

  1. vladpisklov

    Мне помогло просто выгрузить базу в *.dt из sql, загрузить в Postgres, выгрузить обратно в *.dt и опять загрузить

    Reply
  2. vladpisklov

    Мне помогло просто выгрузить базу в *.dt из sql, загрузить в Postgres, выгрузить обратно в *.dt и опять загрузить в SQL. Проблемма исчезла

    Reply
  3. Alfie83

    Мне помог * платформы на предыдущий релиз, где эта ошибка не возникала. Сделал копии поломанных объектов заново в конфигураторе, стараясь избегать объектов ссылочных типов (мне повезло в паре к справочникам поломаны были несколько регистров сведений и накопления). Скопировал информацию оттуда опять же средствами 1с. Старые объекты удалил. И запустил на свежей платформе с перезапуском сервера 1с. Выгрузка или ТиИ занимает много времени поэтому пришлось так.

    Reply
  4. TMV

    (1) кажется и через файловую сработает. Но всё упирается в размер.

    Reply
  5. Дмитрий74Чел

    (2) хитрый ход 😉

    Reply
  6. user1284675

    Что было предпринято и не помогло, на что не стоит тратить время:

    — Тестирование и исправление на уровне конфигуратора — результат: долго проверяет и в итоге вываливает ту же самую ошибку без исправления;

    — Выгрузка базы в Dt –файл и загрузка его в чистую базу – ошибка не исчезает;

    — Выгрузка базы в Dt –файл и загрузка в файловый вариант – ошибка не исчезает;

    — Установка Postgre и загрузка данных туда из Dt –файла, снова выгрузка в Dt –файл и загрузка в базу на SQL север;

    — Тестирование встроенным проверщиком утилитой chdbfl — тоже ничего не нашло и ошибку не исправило.

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

    Что помогло

    купили обработку:

    Однако, в ней нет инструкции, что и как, по чату с разработчиком удалось восстановить целостность базы данных. Обработка помогла, база восстановлена. Рекомендую провести восстановление на копии базы, А затем, когда уже будут готовые текстовые файлы с исправленным содержимым для DBNames и СхемаБазы — просто обновить эти таблицы из этих файлов и после сделать запрос: sp_rename _ReferenceХХXX, _ReferenceYYYY — где ХХХХ номер с задвоением таблиц, YYYY — следующий свободный порядковый номер в таблице имен.

    Если ошибок несколько, то по каждой надо отдельно вносить корректировки.

    Вносить корректировки лучше через автопоиск и автозамену, т.к. малейшие неточности приведут к тому, что при открытии базы получите надпись «Ошибка открытия потока» и восстановить базу можно будет только с бэкапа SQL

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

    Reply
  7. k9260130000

    Благодарю помогло. Но таки поправь в статье — «P.s. после выполнения указанных действий также рекомендую удалить-добавить базу в кластере, или перезапустить службу. » Заменить на п.10 Обязательно удалить/добавить ИБ в кластере .Если просто рестартовать сервер ошибки будут — проверил ((

    Reply
  8. user949348

    Ну и еще «добавить реквизит к объекту и обновить БД» (этот пункт не пробовал, напишите в комментариях — вдруг это самый простой метод) — похоже что да, помогло на версии 8.3.16.1030

    Reply
  9. alena_igorevna

    (8)»добавить реквизит к объекту и обновить БД» если несколько объектов то нужно к каждому добавить. Помогло на платформе 1С:Предприятие 8.3 (8.3.15.1747)

    Reply
  10. user687083_vinsla

    (8) у меня было 40! задублированных ссылочных кодов таблиц. Мне помогла выгрузка данных для перехода в сервис из битой базы и загрузка их в чистую базу. Платформа 8.3.16.1030

    Reply
  11. user949348

    размер базы какой у вас?

    Reply
  12. Дмитрий74Чел

    (10) а где эти пункты меню?

    Reply
  13. Дмитрий74Чел

    (11) 5Гб

    Reply
  14. user687083_vinsla

    (12) В режиме предприятия: Администрирование — Сервис — Выгрузить данные для перехода в сервис. Если команда не видна — в верхнем углу шестеренка — Настройка действий. Там же и команда загрузки данных из сервиса. (11) База небольшая. Для больших баз конечно, наверное, проще возиться с добавлением атрибутов или действовать по плану (6), тут каждый выбирает что ему подходит

    Reply
  15. user949348

    ну тогда можно и dt выгружать пробовать, у нас так не получится, поэтому сразу решили реквизитами пробовать исправлять

    Reply
  16. user646807_kazako.a911

    На мой взгляд не совсем корректное решение. Правильное: https://infostart.ru/public/1147114/

    Reply
  17. Риник

    (16) ахаха ты просто скопировал коммент автора со своего поста и заменил ссылку? Обиделся шоль?)

    Reply
  18. Дмитрий74Чел

    (17) Очевидно да, он обиделся.

    Reply
  19. Дмитрий74Чел

    (16) Ответ на твой вопрос «Чем же решение Дмитрий74Чел корректней (правильней) чем решение user646807_kazako.a911? »

    В решении от user646807_kazako.a911 предложено поменять UUID на произвольный. Не на правильный (которого -то и нет, т.к. проблема не в UUID), а на какой-то там любой.

    Тем более сомнительна рекомендация «В файле «ConfigDumpInfo» UUID объекта можно не менять.». Т.е. в одном месте конфигурации у документа будет один идентификатор, а в другом — другой. На мой взгляд так получаем битую конфигурацию. То, что метод сработал на одной базе скорее всего является следствием лишь того, что в ней указанный документ не использовался.

    В решении Дмитрий74Чел приведены несколько вариантов, как сложных (с заменой номеров объектов), так и простых и 100% безопасных (временное добавление объекту реквизита).

    Reply
  20. ZloyGenii

    Может кто из гуру подскажет как быть в такой ситуации ?

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

    «В процессе обновления информационной базы произошла критическая ошибка

    по причине:

    Ошибка SDBL:

    Ошибка обновления конфигурации базы данных. Для одного ссылочного кода существует более одной таблицы в базе данных.

    Имена таблиц с кодом 18: DataHistoryVersions, Reference18

    Имена таблиц с кодом 19: DataHistoryLatestVersions, Reference19

    Имена таблиц с кодом 20: DataHistoryMetadata, Reference20

    Имена таблиц с кодом 21: DataHistorySettings, Reference21

    Для исправления проблемы вы можете обратиться в службу технической поддержки.»

    Я не наблюдаю в первых ссылках на всякие инструменты хранения истории хоть какой то нумерации, к тому же инструментарий хранения историй полностью выключен… 1С пока что работает под пользователем.

    Добавление реквизитов к выше упомянутым справочникам вообще в принципе ничего не дает… Натолкните куда копать и как решать ? Платформа по сути ругается на все то что связано с инструментом истории данных…

    направьте куда копать….

    Reply
  21. ZloyGenii

    (20)

    В моем случае помогло ПОМИМО добавки временных реквизитов к данным объектам еще смена режима совместимости в конфигураторе на «Версия 8.3.10»

    Может кому то поможет… После данных манипуляций конфигурация обновилась без ошибок.

    Reply
  22. Archidiavol
    Reply
  23. Дмитрий74Чел

    (21) полагаю, ключевое изменение здесь именно понижение версии совместимости. Т.е. по-сути вы просто отключили механизм проверки встроенный в 8.3.15

    Reply
  24. Дмитрий74Чел

    (22) на данный момент по-моему самый просто вариант «добавить реквизит к объекту и обновить БД». В вашем случае — добавить к каждому проблемному объекту.

    Если остался интерес и «битая» база — попробуйте.

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *