Каждый разработчик и администратор баз данных «1С:Предприятие» рано или поздно сталкивается с загадочным поведением автонумерации. Представьте ситуацию: весь год документы создавались последовательно, с аккуратными числовыми номерами вроде 000008633 и 000008634. И вдруг система генерирует номер ООО НПП , после чего как ни в чем не бывало продолжает нумерацию с 000008636. Первая реакция — это недоумение и подозрение на критический сбой кэша платформы.
В этой статье мы подробно разберем, почему возникает подобное поведение, как работает механизм автонумерации в 1С на низком уровне, и как защитить систему от подобных инцидентов.
Проанализируем ситуацию, описанную автором темы. В процессе работы обработки последовательно создавались документы. Номера присваивались следующим образом:
000008633 (успешно создан)000008634 (успешно создан) ООО НПП (внезапное текстовое значение вместо ожидаемого 000008635)000008636 (следующий по порядку корректный номер)На первый взгляд кажется, что метод УстановитьНовыйНомер() дал серьезный технический сбой. Однако в 1С чудес не бывает. Практика показывает, что в 99% случаев за «мистическими» сбоями стоит обычный человеческий фактор — ручное вмешательство пользователя. В данном случае один из операторов случайно или намеренно ввел название контрагента прямо в поле номера документа.
Но почему тогда система не выдала ошибку уникальности и продолжила нумерацию дальше с корректного числа, пропустив ровно один шаг? Чтобы ответить на этот вопрос, нам нужно заглянуть «под капот» платформы «1С:Предприятие 8».
Начиная с версии платформы 8.1, в 1С встроен специальный Менеджер автонумерации. Он призван решить проблему жестких транзакционных блокировок в СУБД.
В старых версиях (например, в 1С 8.0) для получения нового номера платформа выполняла транзакционный запрос к таблице базы данных (условно выбирая максимальный номер через MAX), полностью блокируя таблицу. При высокой интенсивности работы десятков пользователей это гарантированно приводило к частым взаимоблокировкам (Deadlocks).
Современный Менеджер автонумерации работает иначе:
В свойствах любого объекта конфигурации (документа или справочника) существует важнейшая настройка — Режим автонумерации объектов. Рассмотрим два доступных режима:
1. «Освобождать автоматически» (устаревший режим). Если номер был запрошен платформой (например, при открытии формы нового документа), но объект так и не был записан в базу данных (пользователь закрыл форму без сохранения), этот номер возвращается обратно в пул свободных номеров.
2. «Не освобождать автоматически» (стандартный режим по умолчанию для всех современных конфигураций). Как только метод УстановитьНовыйНомер() запрашивает у менеджера очередной номер, этот номер считается выданным и резервируется в кэше сервера. Даже если транзакция записи отменилась, документ закрыли без сохранения или пользователь вручную переписал номер на любой произвольный текст, зарезервированный номер «сгорает» и больше автоматически не предлагается.
Именно этот механизм объясняет пропуск номера в нашей ситуации. Проанализируем хронологию событий по шагам:
000008635. Этот номер резервируется в оперативной памяти сервера приложений. ООО НПП . Документ успешно записывается в базу данных с этим текстом.000008635 считается израсходованным. Оно навсегда уходит из пула автонумерации.УстановитьНовыйНомер() снова обращается к кэшу сервера приложений. Кэш выдает следующий свободный по порядку номер — 000008636.Выясним, почему ручной ввод текста не сломал автонумерацию окончательно. Когда платформа анализирует существующие номера в базе данных для вычисления следующего свободного значения, она применяет строгий алгоритм поиска числовой части:
000008634.000008635. Но так как сервер работал непрерывно и хранил выданный счетчик в памяти, он выдал 000008636.Если вы столкнулись с подобной проблемой, не спешите грешить на динамическое обновление или системные ошибки. Проведите детальное расследование.
Способ 1. Использование Журнала регистрации
Перейдите в Журнал регистрации и установите отбор по метаданным проблемного документа. Найдите событие записи документа с некорректным номером. Вы увидите точное время транзакции и имя пользователя, под сеансом которого было выполнено это действие.
Способ 2. Использование Версионирования объектов
Журнал регистрации может быть очищен или содержать слишком много данных. В этом случае на помощь приходит встроенный механизм версионирования объектов (если он включен в вашей конфигурации). Проанализируем историю изменений документа:
УстановитьНовыйНомер() (скорее всего, там будет правильный числовой номер).В процессе обсуждения проблем с нумерацией часто всплывает рекомендация использовать метод ОбновитьНумерациюОбъектов(). Разберем по шагам, что делает этот метод и когда его безопасно применять.
Этот метод заставляет сервер приложений 1С принудительно обратиться к физическим таблицам СУБД, выполнить поиск максимального номера с учетом префиксов и переинициализировать (обновить) кэш менеджера автонумерации актуальными данными из базы данных.
Вызывать метод можно для конкретного типа объектов:
ОбновитьНумерациюОбъектов(Метаданные.Документы.РеализацияТоваровУслуг);
Важное предостережение: Данный метод сбрасывает все текущие зарезервированные, но еще не записанные в базу данных номера, выданные другим пользователям в этот момент. Если запустить этот метод в разгар рабочего дня, когда в системе одновременно работают десятки операторов, у них при попытке сохранить открытые документы могут массово возникнуть ошибки неуникальности номеров. Применяйте этот метод только в технологические окна или в периоды низкой активности пользователей.
Чтобы шаловливые руки пользователей не ломали автонумерацию и не вводили текстовые наименования в поля номеров, разработчику необходимо внедрить защитные механизмы.
Решение 1. Ограничение прав на редактирование номера на уровне интерфейса
В управляемых или обычных формах документов свойство поля ввода номера «Доступность» или «ТолькоПросмотр» следует устанавливать в значение Истина. Изменение номера должно быть доступно только администраторам системы через специальную роль или по кнопке «Разрешить редактирование номера».
Решение 2. Программный контроль при установке нового номера
Используйте механизм подписок на события или обработчик события ПриУстановкеНовогоНомера в модуле объекта для жесткого контроля формата номера или программной подстановки префиксов:
Процедура ПриУстановкеНовогоНомера(СтандартнаяОбработка, Префикс)
// Автоматически добавляем префикс организации или подразделения
Префикс = Префикс + "ОП-";
КонецПроцедуры
Используя эти несложные правила и понимая внутренние механизмы платформы «1С:Предприятие 8», вы навсегда избавитесь от проблем с автонумерацией и сможете быстро локализовать любые некорректные действия пользователей.