Как исправить ошибку нарушения уникального индекса в таблице среза регистра сведений и нехватку памяти в 1С

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

При выполнении процедуры закрытия месяца, реструктуризации базы данных или операции Тестирование и исправление разработчики и администраторы 1С могут столкнуться со следующей критической ошибкой Microsoft SQL Server: Попытка вставки неуникального значения в уникальный индекс: Не удается вставить повторяющуюся строку ключа в объект "dbo._InfoRgSL..." с уникальным индексом "_InfoR..._ByDims_...". Часто эта проблема сопровождается аварийным завершением рабочих процессов кластера серверов 1С с сообщением о нехватке памяти.

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

Почему возникает ошибка уникальности в таблицах _InfoRgSL

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

  1. _InfoRgSL<ID> (Slice Last) — физическая таблица для хранения актуального среза последних записей.
  2. _InfoRgSF<ID> (Slice First) — физическая таблица для хранения среза первых записей.

В этих таблицах платформа строит уникальный кластерный индекс по измерениям регистра (а также разделителям, если они используются). В идеальном состоянии на каждый уникальный набор ключевых измерений в таблице среза должна приходиться строго одна строка с максимальной датой периода.

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

Определение имени физической таблицы в СУБД

Чтобы точно сопоставить имя таблицы из ошибки SQL (например, _InfoRgSL16148) с конкретным объектом конфигурации 1С, выполним программное сопоставление через метод ПолучитьСтруктуруХраненияБазыДанных(). Напишем и выполним следующий фрагмент кода во внешней обработке:


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

Это позволит однозначно убедиться, какому регистру сведений принадлежит сбойная таблица среза (в типовых конфигурациях чаще всего это регистры ЦеныНоменклатуры, КурсыВалют или ФИОФизЛиц).

Способ 1. Пересоздание таблиц итогов через конфигуратор

Самый безопасный и быстрый способ устранить коллизию в таблицах _InfoRgSL без ручного вмешательства в структуру СУБД — сбросить признак хранения итогов среза:

  1. Откроем базу в режиме Конфигуратор.
  2. Найдем проблемный регистр сведений (например, РегистрыСведений.ЦеныНоменклатуры).
  3. В свойствах регистра снимем флаг Разрешить итоги: срез последних (и Разрешить итоги: срез первых, если он установлен).
  4. Применим изменения в базе данных (клавиша F7). При обновлении конфигурации БД платформа 1С автоматически удалит проблемную физическую таблицу _InfoRgSL и ее уникальные индексы из СУБД.
  5. Запустим операцию Администрирование -> Тестирование и исправление, отметив пункт Пересчет итогов.
  6. Вернемся в свойства регистра, снова установим флаг Разрешить итоги: срез последних и повторно применим изменения конфигурации базы данных (F7). Платформа заново сгенерирует чистую таблицу среза и корректно заполнит ее актуальными данными.

Способ 2. Поиск и программное удаление дублей в регистре

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


ВЫБРАТЬ
    Цены.Период КАК Период,
    Цены.Номенклатура КАК Номенклатура,
    Цены.ВидЦены КАК ВидЦены,
    Цены.Характеристика КАК Характеристика,
    КОЛИЧЕСТВО(*) КАК КоличествоДублей
ИЗ
    РегистрСведений.ЦеныНоменклатуры КАК Цены
СГРУППИРОВАТЬ ПО
    Цены.Период,
    Цены.Номенклатура,
    Цены.ВидЦены,
    Цены.Характеристика
ИМЕЮЩИ
    КОЛИЧЕСТВО(*) > 1

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


Набор = РегистрыСведений.ЦеныНоменклатуры.СоздатьНаборЗаписей();
Набор.Отбор.Период.Установить(НайденныйПериод);
Набор.Отбор.Номенклатура.Установить(НайденнаяНоменклатура);
Набор.Отбор.ВидЦены.Установить(НайденныйВидЦены);

Набор.Прочитать();
// Оставляем только одну актуальную запись, лишние удаляем
Если Набор.Количество() > 1 Тогда
    Пока Набор.Количество() > 1 Цикл
        Набор.Удалить(Набор.Количество() - 1);
    КонецЦикла;
    Набор.Записать(Истина);
КонецЕсли;

Способ 3. Устранение нехватки памяти при закрытии месяца и тестировании

Падение процесса rphost или толстого клиента с ошибкой нехватки памяти (Memory allocation failure) при пересчете итогов за длительный период (несколько лет) обусловлено следующими факторами:

  1. Использование 32-разрядного сервера 1С: Адресное пространство рабочего процесса rphost.exe (32-bit) ограничено 2–4 ГБ оперативной памяти. При тяжелых запросах пересчета итогов регистров за много лет процесс исчерпывает этот лимит и аварийно завершается. Решением является перевод кластера на 64-разрядный сервер 1С:Предприятия.
  2. Ограничения в свойствах кластера: В консоли администрирования кластера серверов 1С проверим параметры Предельный объем виртуальной памяти процессов и Предельный объем памяти рабочих процессов. На время выполнения глобального закрытия месяца или тестирования и исправления рекомендуется временно установить эти параметры в значение 0 (без ограничений), чтобы предотвратить принудительный перезапуск процессов сервером до завершения транзакции.
  3. Очистка кэша метаданных: Искажения в конструкторе запросов (появление ложных циклических веток виртуальных таблиц) свидетельствуют о повреждении локального кэша клиента или серверных контекстов. Остановим службу сервера 1С, очистим каталоги кэша в папке srvinfo (файлы snccntx), а также удалим пользовательские каталоги из %LocalAppData%\1C\1cv8 и %AppData%\1C\1cv8.

Комплексное применение этих шагов позволяет полностью устранить конфликт уникальности в таблицах срезов и успешно завершить регламентные процедуры пересчета итогов.

← На главную