Отказ от ответственности: вы все здесь взрослые и делаете всё на свой страх и риск. Да, и ещё: лицензионное соглашение не разрешает вам это делать, поэтому данное описание дано для образовательных целей.
После перехода с 8.3.12 на 8.3.15 словили неприятную ошибку "Для одного ссылочного кода существует более одной таблицы в базе данных". Самое неприятное, что ошибка стала вылезать и на типовых базах, которые никто никогда не трогал.
Гугл ничего не дал кроме стандартных "почистить кэш, перерегистрировать базу в кластере, выполнить ТИИ". Ну и еще "добавить реквизит к объекту и обновить БД" (этот пункт не пробовал, напишите в комментариях - вдруг это самый простой метод в комментариях к этой статье есть сообщение что метод сработал на 8.3.16.1030, пробуйте). Upd: на данный момент это самый простой и эффективный способ, рекомендую. Но он не работает например для перечислений т.к. у них нет реквизитов.
Другой вариант из комментариев - создать копию базы через РИБ. В копии проблема ушла: "Создал узел для базы (РИБ), потом отвязал эту базу от основной".
Дальше читаем если простой способ не помог.
На партнерке есть пара веток, в т.ч. https://partners.v8.1c.ru/forum/topic/1792992, из которой приведу пару цитат:
Воспроизводится так (проверено на релизе 8.3.13.1644 / SQL 2016):
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 в файл и обратно.
А я опишу методику лечения баз:
- рекомендуется использовать Notepad++ или аналог. В отдельном файле открыть текст ошибки из конфигуратора.
- запустить обработку, получить DBSchema (схема - список объектов - распознать схему) и DBNames (вверху "загрузить из БД в файл"), выгрузить обе структуры в файлы, указав вверху пути и нажав на кнопки "выгрузить схему из списка в файл" и "загрузить из БД в файл". Открыть файлы в Notepad++, выставить синтаксис "С/С#" (или иной - для удобства сворачивания групп). Должно получиться примерно следующее (слева DBNames, справа - DBSchema):
- из текста ошибки для каждой пары объектов выбрать "жертву"; проще менять номер у констант или регистров, т.к. на них обычно нет ссылок в реквизитах других объектов. Желательно выбирать в таком качестве "таблицы изменений" вида _ConstChngR2346 или _DocumentChngR3078 не имеющие табличных частей (у нет таблиц вида Document750.VT20237 или _Reference49197_VT3332).
- в DBNames находим строку жертвы по номеру объекта, переносим строку в конец файла, меняем номер объекта (+1 к предыдущему)
- в файле с текстом ошибки к номеру "жертвы" добавляем "-НовыйНомер"
- в DBSchema находим объект, меняем номер объекта (в третьем параметре); ищем все вхождения имени объекта (например Reference3048) - ссылки на этот объект в реквизитах других объектов - выполняем замену например Reference3048 на Reference49189.
- в DBNames первый параметр меняем на новый максимальный номер объекта
- сохраняем файлы, считываем их обработкой (вся схема - текст - прочитать схему из файла, Имена - Прочитать DBNames из файла), выгружаем из обработки в БД
- пишем 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с на партнерском форуме есть альтернатива - рекомендация перезапускать сервер - в комментариях (7) к данной статье коллега отписался о неэффективности этого метода.
upd 24.01.2020: рекомендую ознакомиться с обработкой из комментария 39.
Понравилась статья? Поставь плюс. Рекомендую другие статьи: