При регулярном разворачивании копий рабочей базы 1С на сервере СУБД для тестирования или разработки специалисты нередко сталкиваются с неприятной ошибкой: при попытке создать новый документ или элемент справочника система генерирует старый номер либо выдает ошибку «Номер не уникален». При этом в рабочей базе нумерация продолжается корректно. Разберем детально, почему так происходит на уровне архитектуры платформы 1С:Предприятие и как гарантированно решить проблему.
Проанализируем механизм автонумерации на стороне сервера 1С:Предприятия. Основная причина кроется в кэшировании счетчиков номеров рабочими процессами кластера серверов rphost:
rphost. Когда администратор восстанавливает резервную копию средствами СУБД (например, в MS SQL Server или PostgreSQL) «на лету» поверх существующей тестовой базы, процессы сервера 1С не перезапускаются и сохраняют старые счетчики из своего кэша. В результате сервер пытается присвоить объекту номер, который в восстановленной базе уже занят более поздними записями.99 вместо 0000000099), платформа при поиске максимума считает строку 99 большей, чем 0000000100, так как символ '9' старше '0'. Это сбивает автоматический механизм автоинкремента.Дата, и только затем вызывать процедуру автонумерации или метод УстановитьНовыйНомер(). В противном случае номер вычисляется для даты по умолчанию, а при смене периода возникает коллизия.Рассмотрим штатный и самый быстрый способ восстановления корректной нумерации без перезапуска всего кластера 1С. В платформе 1С:Предприятие предусмотрен метод глобального контекста ОбновитьНумерациюОбъектов(). Данный метод считывает максимальные номера непосредственно из таблиц базы данных и принудительно обновляет кэш сервера.
Выполнять вызов этого метода разрешено только пользователям с административными правами. Рассмотрим примеры программного вызова:
Для обновления номеров сразу по всем объектам конфигурации (документам, справочникам, бизнес-процессам):
// Сброс и актуализация кэша нумерации для всех объектов метаданных
ОбновитьНумерациюОбъектов();
Если сбой произошел только по определенному типу документов или справочников, можно передать конкретный объект метаданных в качестве параметра:
// Актуализация нумерации только для выбранного документа
ОбновитьНумерациюОбъектов(Метаданные.Документы.РеализацияТоваровУслуг);
// Актуализация нумерации для конкретного справочника
ОбновитьНумерациюОбъектов(Метаданные.Справочники.Номенклатура);
Также метод принимает массив объектов метаданных, если требуется обновить лишь определенную группу сущностей:
МассивМетаданных = Новый Массив;
МассивМетаданных.Добавить(Метаданные.Документы.ПоступлениеТоваровУслуг);
МассивМетаданных.Добавить(Метаданные.Документы.РеализацияТоваровУслуг);
МассивМетаданных.Добавить(Метаданные.Документы.СчетНаОплатуПокупателю);
ОбновитьНумерациюОбъектов(МассивМетаданных);
Важно: После вызова метода ОбновитьНумерациюОбъектов() все ранее выданные сеансам, но еще не записанные в базу номера становятся невалидными.
Чтобы исключить проблему расхождения кэша и данных при регулярном автоматическом обновлении тестовых контуров из ночных бэкапов, скорректируем административный регламент разворачивания баз. Разберем правильную последовательность шагов:
rphost не задействуется.ragent) сразу после наката резервной копии.ОбновитьНумерациюОбъектов() в скрипт автоматической постобработки базы при первом запуске под служебным пользователем через ключ командной строки /C.