При обновлении конфигурации или выполнении реструктуризации базы данных администраторы и программисты 1С часто сталкиваются с критической ошибкой SQL: «Попытка вставки неуникального значения в уникальный индекс». Особенно неприятно, когда эта ошибка возникает на этапе создания временных таблиц (индекс с суффиксом NG), а стандартные средства вроде «Тестирования и исправления» (ТиИ) не показывают никаких проблем. Рассмотрим детально, почему это происходит и как вылечить базу данных, если обычные методы бессильны.
Проанализируем ситуацию. Ошибка вида CREATE UNIQUE INDEX прервано, поскольку обнаружен повторяющийся ключ для объекта с именем "dbo._DocumentJournalXXXXXNG" означает, что в процессе реструктуризации 1С создает новую версию таблицы журнала документов (с суффиксом NG — New Generation) и пытается перенести туда данные из старой таблицы. В процессе переноса платформа обнаруживает, что две записи имеют одинаковый набор полей, входящих в уникальный индекс (обычно это ссылка на документ _DocumentRRef и тип документа).
Одной из ключевых причин в современных версиях платформы (начиная с 8.3.16) является официально признанная ошибка 10221419. Она проявляется в тех случаях, когда документ включен в план обмена в расширении конфигурации, и при этом данный документ входит в состав журнала документов в основной конфигурации. В момент реструктуризации происходит конфликт метаданных, и система пытается дважды зарегистрировать одну и ту же запись в журнале.
Прежде чем приступать к «лечению», нам нужно точно понять, какой документ вызывает сбой. Посмотрим на значение ключа из текста ошибки: (0, 0x00000265, 0x80e2001e674d523c11e4d36c6e75dd82).
0x00000265) — это внутренний идентификатор типа объекта (Metadata ID).0x80e2...) — это уникальный идентификатор (GUID) конкретной записи документа.Чтобы найти этот документ в базе 1С, выполним в консоли запросов простой запрос, подставив полученный GUID:
ВЫБРАТЬ
Ссылка
ИЗ
Документ.СчетНаОплатуПокупателю // Замените на предполагаемый тип документа
ГДЕ
Ссылка = ССЫЛКА(Документ.СчетНаОплатуПокупателю, "80e2001e-674d-523c-11e4-d36c6e75dd82")
Если тип документа неизвестен, его можно вычислить по имени таблицы _DocumentJournalXXXXX в SQL, посмотрев структуру таблиц в 1С (через консоль запросов или обработку «Структура таблиц БД»).
Проверим таблицу журнала на наличие физических дублей, которые «не видит» 1С. Для этого выполним запрос в консоли SQL Server Management Studio (SSMS):
SELECT _DocumentRRef, COUNT(*)
FROM _DocumentJournal61795 // Имя вашей таблицы из ошибки
GROUP BY _DocumentRRef
HAVING COUNT(*) > 1
Если запрос вернул строки — значит, в журнале действительно есть «зависшие» записи-сироты. Если запрос пуст, значит проблема носит логический характер и возникает именно в момент работы механизмов реструктуризации платформы.
Если простое удаление расширений не помогает, применим радикальный, но проверенный способ «перезагрузки» данных проблемного типа документа. Разберем его по шагам:
TRUNCATE TABLE _Document255; -- Имя таблицы вашего документа
Поскольку мы выяснили, что причиной часто является баг 10221419, проанализируем наши расширения. Рассмотрим альтернативный (более простой) путь, который помогает в ряде случаев:
Иногда современные механизмы оптимизированной реструктуризации (появившиеся в платформе 8.3.15+) ведут себя некорректно. Попробуем заставить платформу работать по старинке (построчно).
Для этого в файле conf.cfg (находится в папке conf в каталоге установки платформы 1С) добавим строку:
DisableOptimizedRestructuring=1
Или запустим конфигуратор с параметром командной строки:
/IBCheckAndRepair -Rebuild
Проанализируем результат. Старый механизм реструктуризации более медленный, но он менее чувствителен к определенным видам несогласованности данных в индексах журналов.
Выясним, не повреждена ли база данных на физическом уровне. Даже если 1С молчит, выполним команду SQL:
DBCC CHECKDB ('ВашаБазаДанных') WITH NO_INFOMSGS, ALL_ERRORMSGS;
Если обнаружены ошибки, используйте REPAIR_ALLOW_DATA_LOSS, но помните, что это крайняя мера. В большинстве случаев проблема «неуникального значения» в журналах решается именно через временное исключение типа документа из состава журнала в метаданных и последующий пересчет (как описано в Шаге 3).
Помните, что перед любыми манипуляциями с таблицами SQL или массовыми операциями в конфигураторе создание резервной копии базы данных (.dt или бэкап SQL) является обязательным условием.