В процессе работы с программными продуктами «1С:Предприятие 8» пользователи и администраторы часто сталкиваются с неочевидным поведением системы при нумерации документов. Типичная ситуация: пользователь нажимает кнопку «Создать», открывается форма нового документа, и система автоматически показывает ему следующий по порядку номер (например, 000001). Если пользователь передумывает, закрывает форму без сохранения, а затем снова пытается создать документ, новый объект неожиданно получает номер 000002. Куда исчез первый номер? Почему система зарезервировала его и «потеряла»? Разберем подробно технические причины этого поведения и рассмотрим правильные варианты решения этой проблемы в современных реалиях разработки.
Для того чтобы понять, почему платформа ведет себя именно так, заглянем во внутреннее устройство системы. На самом верхнем уровне дерева метаданных в свойствах конфигурации существует важная настройка под названием «Режим автонумерации объектов». Этот параметр определяет, как именно СУБД и сервер приложений взаимодействуют с генератором номеров для документов и кодов справочников.
Данный параметр может принимать два значения:
Давайте проанализируем, почему разработчики платформы приняли решение отказаться от автоматического освобождения номеров и сделать режим «Не освобождать автоматически» основным.
На первый взгляд кажется, что режим «Освобождать автоматически» гораздо удобнее и логичнее, ведь он исключает «дыры» и пропуски в нумерации, которые так не любят бухгалтеры и аудиторы. Однако в многопользовательских базах данных этот режим вызывает критические проблемы с производительностью и стабильностью:
Во-первых, это вызывает избыточные блокировки базы данных. Чтобы система точно знала, какие номера свободны, а какие освободились, ей приходится постоянно опрашивать таблицы базы данных и блокировать их при генерации каждого нового номера. При одновременной работе десятков и сотен пользователей это неизбежно приводит к эскалации блокировок, зависаниям интерфейса и ошибкам ожидания блокировок СУБД.
Во-вторых, возникают конфликты транзакций. Если два бухгалтера одновременно открывают новые документы одного вида, система при включенном режиме автоматического освобождения может попытаться выдать им один и тот же «освободившийся» номер. При попытке одновременной записи этих документов один из пользователей гарантированно получит ошибку неуникальности номера, и его транзакция будет отменена.
Режим «Не освобождать автоматически» решает эти проблемы. Он работает значительно быстрее в клиент-серверных базах данных, поскольку сервер приложений выдает номера из кэша и не выполняет постоянные ресурсоемкие проверки таблиц СУБД на наличие освободившихся номеров.
Если в вашей базе данных начали пропускаться номера, простым переключением глобального режима автонумерации в конфигураторе на «Освобождать автоматически» проблему решать не рекомендуется. Это существенно замедлит работу системы и может привести к техническим сбоям. Вместо этого рассмотрим три правильных и современных подхода к решению проблемы.
Это самый надежный и современный архитектурный подход, который применяется во всех типовых решениях «1С:Предприятия 8» (например, в «1С:Бухгалтерии 3.0», «1С:ERP» или «1С:Управлении торговлей 11»).
Суть метода заключается в том, что пока пользователь заполняет документ на экране, у этого документа вообще нет номера. Поле ввода номера на форме часто делается недоступным для редактирования или скрывается. Номер генерируется системой непосредственно в момент нажатия кнопки «Записать» или «Провести» внутри транзакции записи.
Для реализации этого механизма в свойствах формы документа параметр Автонумерация переводится в значение Не использовать, а генерация номера переносится на серверную сторону. Рассмотрим пример программного кода, который можно использовать в модуле объекта документа перед его записью в базу данных:
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
Если ЭтоНовый() И Не ЗначениеЗаполнено(ЭтотОбъект.Номер) Тогда
// Платформа автоматически сгенерирует номер непосредственно в момент транзакции записи
ЭтотОбъект.УстановитьНовыйНомер();
КонецЕсли;
КонецПроцедуры
Этот подход полностью устраняет проблему пустых номеров. Пользователь может открывать и закрывать сколько угодно экранных форм, номера при этом расходоваться не будут. Номер присвоится только в тот момент, когда документ гарантированно сохранится в базу данных.
Иногда пропуски номеров возникают из-за того, что в кэше сервера приложений «залипли» неиспользованные номера, и платформа продолжает отсчет со слишком большого значения. В таких случаях можно выполнить принудительное обновление кэша номеров для конкретного объекта метаданных.
Для этого используется встроенный метод платформы ОбновитьНумерациюОбъектов(). Мы можем запустить специальную обработку или выполнить этот код во внешнем соединении:
// Обновляем нумерацию для конкретного вида документа
ОбновитьНумерациюОбъектов(Метаданные.Документы.РеализацияТоваровУслуг);
Этот метод полностью очищает кэш номеров в оперативной памяти сервера и актуализирует его на основе реально записанных документов в базе данных. После выполнения этой команды платформа найдет самый большой физически существующий номер в базе данных и продолжит нумерацию строго со следующего за ним значения.
Часто проблема с автонумерацией возникает по вине самих пользователей. Если кто-то вручную отредактировал номер документа (например, вместо «0000-000025» написал «0000-00025» или случайно стер лидирующие нули, добавил лишние буквы), платформа теряет способность правильно распознавать префиксы и длину номера. В результате автонумерация сбивается, и номера начинают генерироваться некорректно или пропускаться.
Давайте разберем по шагам, как исправить сбившуюся нумерацию вручную:
ОбновитьНумерациюОбъектов() для данного документа, чтобы сбросить кэш.После выполнения этих действий платформа подхватит корректный шаблон и возобновит правильную последовательную генерацию номеров без пропусков.