При автоматической загрузке данных, выполнении интеграционных процедур или работе регламентных заданий разработчики 1С нередко сталкиваются с ситуацией, когда при программной записи нового элемента справочника система генерирует ошибку: «Код не уникален». При этом настройки метаданных заданы корректно — включена автонумерация, контроль уникальности установлен «Во всем справочнике», ручной ввод пользователями исключен, а код в модуле формирует элементы последовательно в один поток.
Разберем причины возникновения такого поведения платформы 1С и выясним, как правильно восстановить корректную автонумерацию.
Рассмотрим типовой пример программного кода, в котором возникает данная ошибка:
Новая_EDI_РН = Справочники.EDI_РН.СоздатьЭлемент();
Новая_EDI_РН.ДатаФормирования = ТекущаяДата();
Новая_EDI_РН.KEY = КлючЗагрузки;
Новая_EDI_РН.НомерДокумента1С = НомерРН;
Новая_EDI_РН.ДатаДокумента1С = ДатаРН;
Новая_EDI_РН.Заявка_EDI = Найденный_EDI_Заказ;
Новая_EDI_РН.Представительство = Найденный_EDI_Заказ.Представительство;
Новая_EDI_РН.Записать();
В момент вызова метода Записать() платформа автоматически пытается определить следующий свободный номер/код. Однако вместо нового максимального значения подставляются уже существующие в базе коды (например, 544, 545, 546 и т.д.), что приводит к прерыванию транзакции.
Проанализируем основные технические причины, приводящие к рассинхронизации счетчика автонумерации в платформе 1С:
rphost) кэширует в оперативной памяти интервалы кодов и номеров. При аварийном завершении процесса, перезапуске служб или сбоях связи кэшированные значения в памяти могут разойтись с фактическим максимальным кодом в таблице базы данных СУБД.ОтменитьТранзакцию(), запрошенный номер может по-прежнему числиться в кэше как занятый или застрять на предыдущем значении.rphost, один процесс может не сразу получить актуальный срез максимального значения, зафиксированного в другом процессе.Основным и наиболее быстрым решением является принудительное обновление пространства номеров с помощью встроенного метода платформы ОбновитьНумерациюОбъектов(). Этот метод заставляет платформу перечитать реальные максимальные коды из таблиц СУБД и перестроить кэш нумератора.
Вызов метода без параметров выполняет обновление для всех объектов конфигурации, что при большом объеме данных создает избыточную нагрузку на базу данных:
// Не рекомендуется на высоконагруженных базах:
ОбновитьНумерациюОбъектов();
Оптимальным решением является точечное обновление нумерации конкретного справочника путем передачи в метод объекта метаданных:
// Точечное обновление нумерации для конкретного справочника:
ОбновитьНумерациюОбъектов(Метаданные.Справочники.EDI_РН);
Также метод поддерживает передачу массива объектов метаданных, если требуется сбросить нумерацию для нескольких справочников или документов одновременно.
Если в коде загрузки требуется гарантировать присвоение номера до выполнения события записи, вызовем метод объекта УстановитьНовыйКод():
Новая_EDI_РН = Справочники.EDI_РН.СоздатьЭлемент();
// Явно инициируем генерацию автокода до заполнения и записи
Новая_EDI_РН.УстановитьНовыйКод();
Новая_EDI_РН.ДатаФормирования = ТекущаяДата();
Новая_EDI_РН.KEY = КлючЗагрузки;
Новая_EDI_РН.НомерДокумента1С = НомерРН;
Новая_EDI_РН.ДатаДокумента1С = ДатаРН;
Новая_EDI_РН.Заявка_EDI = Найденный_EDI_Заказ;
Новая_EDI_РН.Представительство = Найденный_EDI_Заказ.Представительство;
Новая_EDI_РН.Записать();
Если программный сброс не дал результата, очистить зависший кэш в оперативной памяти сервера можно на уровне инфраструктуры:
rphost через консоль администрирования кластера серверов 1С.1C:Enterprise 8.3 Server Agent.При проектировании структуры справочников обратим внимание на следующие особенности:
Число(38) создает повышенную нагрузку на СУБД при наложении индексных блокировок. Если справочник хранит внешние идентификаторы или технические сущности, рекомендуется использовать уникальные строковые идентификаторы UUID (GUID) либо хранить внешние ключи в отдельном реквизите, отключив контроль уникальности стандартного кода.