При работе с базами данных 1С программисты часто сталкиваются с ситуацией, когда после разворачивания копии базы, переноса данных или некорректного программного вмешательства «слетает» автонумерация документов. Обычный вызов команды ОбновитьНумерациюОбъектов() не всегда помогает с первого раза, особенно если в системе задействованы сложные механизмы записи или дополнительные объекты, такие как СМС-уведомления или записи в регистрах. Разберем подробно, как работает этот механизм, почему возникают ошибки неуникальности и как правильно привести нумерацию в порядок.
Для понимания сути проблемы важно осознать, что платформа 1С не обращается к таблицам базы данных SQL за «следующим номером» каждый раз, когда пользователь создает новый документ. Это было бы слишком медленно и создавало бы избыточную нагрузку. Вместо этого используется механизм кэширования номеров на стороне сервера 1С.
Проанализируем этот процесс: сервер приложений «захватывает» диапазон номеров (обычно 10 штук) и хранит их в оперативной памяти. Когда пользователь нажимает кнопку «Создать», сервер выдает следующий номер из этого кэша. Проблема возникает в тот момент, когда мы восстанавливаем базу из копии: сервер приложений может «думать», что следующий свободный номер — 100, в то время как в самой базе данных (в таблицах SQL) уже существуют документы с номерами до 150. При попытке записи возникает коллизия.
Рассмотрим ситуацию автора: вызов ОбновитьНумерациюОбъектов(Метаданные.Документы.ИмяДокумента) вроде бы починил ручное создание документов, но программный код (формирование СМС) продолжает выдавать ошибку Значение "567480" поля "Номер" не уникально. Выясним причину этого странного поведения.
Нумератор, то обновление нумерации по конкретному документу может не сработать. Нужно обновлять именно Нумератор.Док.Записать(РежимЗаписиДокумента.Запись) внутри обработки проведения или в цепочке событий ПриЗаписи, платформа пытается зафиксировать номер. Если кэш сервера не был сброшен полностью для всех затронутых объектов, система наткнется на уже существующий в базе номер.Для гарантированного решения проблемы рекомендуется выполнить комплекс мер. Рассмотрим их последовательно.
Вместо того чтобы обновлять каждый документ по отдельности, выполним команду без параметров. Это заставит платформу пересчитать последние номера для всех справочников и документов в системе, а также сбросит все серверные кэши.
// Выполняется под администратором системы
ОбновитьНумерациюОбъектов();
Этот метод просканирует таблицы базы данных, найдет максимальные значения и установит внутренние счетчики платформы в актуальное состояние.
Команда ОбновитьНумерациюОбъектов бессильна, если в базе данных есть номера, нарушающие логику приращения. Проанализируем ситуацию: если у вас длина номера 11 знаков (например, «00000000001») и кто-то вручную ввел номер «99999999999», то платформа не сможет вычислить «следующий» номер, так как достигнут предел разрядности. Также часто мешают номера, где префикс написан в другой раскладке (латиница вместо кириллицы).
Рекомендуется запустить простую обработку или воспользоваться консолью запросов, чтобы найти такие «аномальные» номера и исправить их (например, добавить в конец старого номера символ или просто перенумеровать последние документы).
Посмотрим на важное свойство в корне конфигурации. В окне свойств дерева метаданных найдите пункт «Режим автонумерации объектов». Он может принимать два значения:
В некоторых случаях (особенно в клиент-серверном варианте) даже после выполнения программных команд сервер 1С может удерживать старые значения в памяти. Если проблема сохраняется, выполним следующие действия:
snccntx в каталоге описания кластера (обычно это C:\Program Files\1cv8\srvinfo).Если вы пишете сложный функционал, где документ записывается программно, можно подстраховаться и принудительно запросить новый номер перед записью. Разберем пример кода:
Попытка
// Если мы создаем новый объект или хотим пересчитать номер
Если Док.ЭтоНовый() Тогда
Док.УстановитьНовыйНомер(ПрефиксОрганизации);
КонецЕсли;
Док.Записать(РежимЗаписиДокумента.Запись);
Исключение
Сообщить("Ошибка при записи: " + ОписаниеОшибки());
// Если ошибка всё еще в уникальности, возможно,
// стоит проверить связанные объекты в этой транзакции
КонецПопытки;
Подведем итоги. Механизм ОбновитьНумерациюОбъектов — это мощный инструмент, но он работает эффективно только тогда, когда данные в таблицах соответствуют маскам нумерации. Если вы столкнулись с ошибкой неуникальности в копии базы:
ОбновитьНумерациюОбъектов() без параметров.Помните, что номера в 1С — это строковые значения, и их сравнение происходит лексикографически. Порядок «1, 10, 2» для системы является нормальным, если не соблюдена лидирующая нулями длина номера. Следите за единообразием префиксов и длиной номеров, чтобы автонумерация работала без сбоев.