Каждый администратор СУБД и разработчик 1С рано или поздно сталкивается с неприятной ситуацией: после успешного восстановления резервной копии базы данных (например, созданной с помощью утилиты pg_dump для PostgreSQL или средствами MS SQL Server) пользователи начинают жаловаться на ошибки при записи новых документов. Платформа выдает системное сообщение «Значение поля "Номер" не уникально», либо автоматически присваивает новым документам старые номера, которые использовались месяцы или даже годы назад.
В этой статье мы подробно разберем, почему возникает этот сбой, как устроен внутренний механизм автонумерации в платформе «1С:Предприятие 8.3», и рассмотрим пошаговые методы исправления нумерации — от быстрых программных способов до администрирования сервера приложений.
Для того чтобы понять природу проблемы, проанализируем поведение платформы 1С. Начиная с версии 8.1, в целях повышения производительности и исключения избыточных блокировок таблиц СУБД, разработчики платформы внедрили специальный механизм — Менеджер автонумерации.
Работает этот механизм по принципу кэширования:
rphost) не делает тяжелый запрос ко всей таблице базы данных СУБД для поиска максимального номера.Проблема «слепоты» сервера приложений возникает тогда, когда мы производим манипуляции с базой данных в обход самого сервера 1С. Когда вы восстанавливаете резервную копию базы данных непосредственно на уровне СУБД (PostgreSQL, MS SQL и др.), сервер приложений 1С физически не может отследить это изменение. Для процесса rphost сессия работы с базой данных не прерывалась, и в его оперативной памяти продолжает находиться старый кэш автонумерации, актуальный на момент *до* восстановления копии (или соответствующий другой базе, если восстановление шло «поверх» существующей схемы).
В результате сервер пытается выдать очередной номер из своего кэша, но в восстановленной физической таблице базы данных этот номер уже занят существующим документом. Происходит конфликт уникальности.
Интересный факт: если в такой ситуации вручную изменить номер документа на действительно уникальный (следующий по порядку после актуального максимального) и сохранить документ, автонумерация для этого типа метаданных восстанавливается. Это происходит потому, что при успешной записи объекта с номером, превышающим кэшированный, платформа принудительно перезаписывает значение кэша в оперативной памяти сервера приложений.
Рассмотрим самый быстрый, элегантный и технологичный способ решения проблемы. Платформа 1С предоставляет штатный метод встроенного языка для принудительного сброса кэша автонумерации. Этот метод заставляет сервер приложений стереть данные из оперативной памяти и заново вычислить максимальные номера непосредственно из физических таблиц СУБД.
Преимущество этого метода заключается в том, что он не требует монопольного режима и перезапуска служб. Вы можете выполнить его в любой момент прямо в работающей базе.
Для этого мы можем написать простую внешнюю обработку или воспользоваться групповой обработкой данных. Рассмотрим пример кода:
// Пример 1. Сброс кэша автонумерации для абсолютно всех объектов в базе данных
ОбновитьНумерациюОбъектов();
// Пример 2. Сброс кэша для конкретного типа документов (например, Реализация товаров и услуг)
ОбновитьНумерациюОбъектов(Метаданные.Документы.РеализацияТоваровУслуг);
// Пример 3. Сброс кэша для списка конкретных документов через массив
МассивМетаданных = Новый Массив;
МассивМетаданных.Добавить(Метаданные.Документы.ЗаказПокупателя);
МассивМетаданных.Добавить(Метаданные.Документы.ПоступлениеТоваровУслуг);
ОбновитьНумерациюОбъектов(МассивМетаданных);
После выполнения данного кода платформа актуализирует кэш в памяти rphost, и последующие новые документы будут создаваться без ошибок уникальности.
Если у вас нет возможности или прав для запуска внешних обработок с кодом, проанализируем системный подход. Поскольку кэш номеров живет исключительно в оперативной памяти процессов сервера приложений, самый простой способ очистить его — перезапустить службу сервера «1С:Предприятия».
Разберем по шагам, как это сделать:
services.msc), найдите службу Агент сервера 1С:Предприятия 8.3 и выполните команду Перезапустить.systemctl restart srv1cv83 (или соответствующее имя службы в вашей системе).
При старте службы процессы rphost инициализируются заново. При первом обращении пользователей к созданию документов платформа считает актуальные максимальные номера напрямую из таблиц СУБД.
Важное ограничение: данный метод перезапускает весь кластер серверов 1С. Если на данном сервере крутится множество других рабочих баз данных, сеансы всех пользователей в этих базах будут аварийно завершены. Поэтому этот метод хорош только для выделенных тестовых серверов.
Что делать, если перезапускать весь сервер приложений нельзя, так как на нем работают сотни пользователей в других базах, но очистить кэш конкретной восстановленной копии необходимо? Рассмотрим метод перерегистрации базы.
Для этого выполним следующие действия:
Для кластера 1С эта база станет абсолютно «новой». Сервер приложений создаст для нее чистые структуры в своей оперативной памяти, не содержащие устаревших кэшей, и нумерация сразу же начнет работать корректно.
Проанализируем еще одну критическую ошибку администрирования, которая упоминается практикующими специалистами. Иногда при развертывании тестовых сред администраторы случайно подключают к одной и той же физической базе СУБД два разных кластера 1С (например, рабочий сервер приложений и тестовый сервер приложений).
В этом случае происходит неизбежная рассинхронизация:
Важное правило: никогда не подключайте несколько серверов или кластеров 1С к одной физической базе данных на СУБД. Это гарантированно приведет к порче данных и постоянным конфликтам блокировок и уникальности номеров.
Иногда сбой автонумерации никак не связан с восстановлением бэкапов, а вызван некорректными действиями пользователей. Достаточно одному сотруднику вручную отредактировать номер документа и случайно поставить туда лишний символ, как встроенный парсер 1С ломается.
Типичные ошибки ручного ввода:
00000857 ввести 000О0857)./) или дефисов в конец номера.В таких случаях платформа больше не может автоматически прибавить единицу к текстовому представлению номера. Чтобы решить эту проблему, выполните следующие действия:
ОбновитьНумерациюОбъектов() для очистки кэша, зафиксировавшего ошибочный номер.Чтобы минимизировать риски возникновения ошибок уникальности номеров при развертывании тестовых баз из резервных копий, мы рекомендуем придерживаться следующей методологии:
DROP DATABASE) в СУБД, а не просто заменяйте таблицы.ОбновитьНумерациюОбъектов() сразу после развертывания копий по расписанию.