При обновлении или реструктуризации большой информационной базы в клиент-серверном варианте администраторы и разработчики нередко сталкиваются с критической ошибкой: «Нарушено условие уникальности данных. Попытка вставки неуникального значения в уникальный индекс». Особенно неприятно, когда ошибка указывает на таблицу с суффиксом NG (например, _DocumentJournal28036NG) и происходит в процессе создания уникального индекса. Ситуация осложняется тем, что стандартная выгрузка в файловый вариант (dt) для исправления часто невозможна из-за огромного объема данных.
В этой статье мы подробно разберем, почему возникает эта ошибка, как расшифровать сообщение SQL Server и какие шаги необходимо предпринять для восстановления работоспособности базы, используя инструменты SQL и знания о внутренней структуре 1С.
Для начала проанализируем, что именно происходит в момент ошибки. Когда платформа 1С выполняет реструктуризацию таблицы (например, при изменении состава журнала документов или добавлении реквизита в расширение), она не меняет основную таблицу напрямую. Вместо этого создается временная таблица с суффиксом NG (Next Generation). Платформа переносит данные из старой таблицы в новую, после чего пытается создать индексы. Если в переносимых данных оказываются дубли по полям, входящим в уникальный индекс, SQL Server прерывает операцию CREATE UNIQUE INDEX.
Наличие в ошибке букв NG в имени таблицы — это прямой признак того, что сбой произошел именно в процессе «переезда» данных в новую структуру. Если процесс прервался, эта временная таблица может остаться в базе данных, мешая последующим попыткам обновления.
В тексте ошибки SQL обычно указывает конкретное повторяющееся значение ключа. Например: (0, 0x000002aa, 0x818fc8d3a384789d11eb6239840abf1b). Разберем, что скрывается за этими шестнадцатеричными числами:
_DocumentTRef. Оно определяет тип документа. Чтобы перевести его в понятный вид, отбросим 0x и преобразуем 2AA из шестнадцатеричной системы в десятичную — получаем 682._DocumentRRef. Это уникальный идентификатор (GUID) конкретного документа в базе данных.Чтобы выяснить, какой именно тип документа вызывает проблему, выполним запрос в SQL Server Management Studio (SSMS) к таблице метаданных:
SELECT * FROM [dbo].[_MetadataId]
WHERE [_TypeID] = 2 AND [_Tid] = 682
Здесь _TypeID = 2 указывает на то, что мы ищем среди документов, а _Tid — это наше число 682. В результате мы получим имя таблицы документа, который породил дубль в журнале.
Теперь нам нужно найти записи, которые платформа считает одинаковыми. Рассмотрим пример запроса для поиска дублей в конкретном журнале (в нашем случае это _DocumentJournal28036). Мы будем искать записи, у которых совпадают тип документа и его ссылка.
Выполним следующий запрос для диагностики:
SELECT [_DocumentTRef] AS RefType,
[_DocumentRRef] AS Ref,
COUNT(*) as CountOfDuplicates
FROM [dbo].[_DocumentJournal28036] WITH (NOLOCK)
GROUP BY [_DocumentTRef], [_DocumentRRef]
HAVING COUNT(*) > 1
Если запрос вернул строки, значит, в основной таблице журнала уже содержатся логические дубли. Такое бывает при сбоях прошлых обновлений или некорректной работе расширений. Чтобы увидеть данные этих документов, используем полученный ранее _DocumentRRef:
SELECT * FROM [dbo].[_DocumentJournal28036]
WHERE [_DocumentRRef] = 0x818fc8d3a384789d11eb6239840abf1b
Часто ошибка связана не с самой основной базой, а с механизмом расширений. Платформа 1С для хранения данных расширений создает дополнительные таблицы с суффиксами вроде X1. Если вы изменили состав журнала в расширении, 1С может ошибочно пытаться объединить данные основной таблицы и таблицы расширения, получая дубли по ссылкам.
Рассмотрим алгоритм проверки таблиц расширений:
_Document332) через _MetadataId._Document332X1).
SELECT COUNT(*) FROM _Document332;
SELECT COUNT(*) FROM _Document332X1;
Проанализируем ситуацию: если в обеих таблицах есть данные по одной и той же ссылке, это и есть причина конфликта. В некоторых случаях (согласно опыту коллег) помогает полная очистка таблицы расширения, если данные в ней дублируют основную базу, командой TRUNCATE TABLE _Document332X1, но делать это можно только после тщательного анализа и создания бэкапа!
Если поиск и удаление дублей через SQL не помогают или дубли появляются вновь при каждой попытке обновления, велика вероятность, что мы столкнулись с зарегистрированной ошибкой платформы (например, ошибка 10235932). В этом случае рассмотрим альтернативные варианты решения:
Вариант А: Манипуляции с расширениями. Попробуем временно отключить или удалить расширение, которое вносит изменения в структуру проблемного журнала или справочника. В ряде случаев достаточно сделать расширение «неактивным», провести обновление конфигурации базы данных, а затем снова включить его.
Вариант Б: Смена версии платформы. Механизм реструктуризации значительно менялся в версиях 8.3.21, 8.3.22 и выше. Иногда «оптимизированная реструктуризация» работает некорректно с конкретными данными. Как показывает практика, если обновление падает на 8.3.24, имеет смысл попробовать выполнить его на более старой, стабильной ветке (например, 8.3.21), а после успешного завершения вернуться на актуальную версию.
Если вы точно установили, что в таблице журнала присутствуют две абсолютно идентичные записи с одинаковыми _DocumentTRef и _DocumentRRef, одну из них придется удалить напрямую через SQL. Внимание! Это крайняя мера. Перед любыми действиями по удалению обязательно создайте резервную копию базы данных.
Пример безопасного подхода:
CTID или другой внутренний идентификатор строки (в SQL Server можно использовать row_number()), чтобы отличить одну запись от другой.Рассмотрим пример запроса для удаления дублей, оставляя только одну запись с минимальным системным идентификатором (если он есть):
WITH CTE AS (
SELECT TOP 100 * -- всегда проверяйте выборку перед удалением!
FROM [dbo].[_DocumentJournal28036]
WHERE [_DocumentRRef] = 0x818fc8d3a384789d11eb6239840abf1b
)
-- DELETE FROM CTE; -- Раскомментируйте после проверки
Подведем итог нашему исследованию. Ошибка уникальности индекса в таблицах NG — это сложная техническая проблема, требующая понимания структуры SQL-таблиц 1С. Для её решения мы:
_DocumentTRef и находить проблемные типы объектов.Помните, что работа напрямую с таблицами SQL — это вмешательство в механизмы платформы. Всегда начинайте с простых методов: очистки кэша сервера 1С, тестирования и исправления, и только в случае неудачи переходите к прямым SQL-запросам. Для автоматизации регулярного резервного копирования, проверки и технического обслуживания баз можно использовать программу для автоматического тестирования, архивирования и обновления 1С.