Почему зависает 1С при установке нового кода справочника и как это исправить?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В процессе разработки и сопровождения конфигураций на платформе 1С:Предприятие 8.3 программисты иногда сталкиваются с необходимостью изменения метаданных существующих объектов. Одной из таких задач является смена типа кода справочника, например, с типа Строка на тип Число. Казалось бы, простая операция в конфигураторе может привести к серьезной проблеме: при попытке записи нового элемента или вызове метода УстановитьНовыйКод() сеанс пользователя полностью зависает. Рассмотрим подробно, почему это происходит и как правильно диагностировать и устранить данную неисправность.

Анализируем причины возникновения проблемы

Когда мы меняем тип кода, платформа должна полностью перестроить логику генерации новых значений. Проблема зависания в версии 8.3.14 и выше чаще всего связана не с самой записью данных, а с работой сервиса нумерации в кластере 1С и механизмом блокировок в СУБД. Разберем основные факторы, которые приводят к «мертвому» зависанию:

  1. Кэширование в менеджере кластера. Платформа 1С оптимизирует выдачу номеров и кодов, выделяя их «порциями» и сохраняя последнее значение в оперативной памяти процесса rmngr. После изменения типа данных в метаданных старый строковый кэш может конфликтовать с новыми числовыми требованиями.
  2. Блокировки в транзакции СУБД. При установке нового кода система пытается найти максимальное значение в таблице. Если индексы не обновлены или в таблице присутствуют записи, которые SQL-сервер не может однозначно интерпретировать как числа, запрос SELECT MAX может вызвать эксклюзивную блокировку таблицы REFLOCK, ожидая завершения неопределенного процесса.
  3. Бесконечные циклы в обработчиках. Нельзя исключать и программные ошибки в модулях объекта или подписках на события.

Шаг 1. Проверяем программный код и подписки

Прежде чем переходить к настройкам сервера, исключим вероятность зацикливания кода. Проанализируем обработчики событий, которые срабатывают при установке нового кода. Нам необходимо проверить:

Для диагностики выполним замер производительности. Если при вызове метода УстановитьНовыйКод() замер показывает бесконечное выполнение одной и той же строки или просто «пропадает» в системных функциях, следует временно закомментировать содержимое обработчиков. Рассмотрим типичный пример опасного кода, который может вызвать проблемы при смене типа:


Процедура ПриУстановкеНовогоКода(СтандартнаяОбработка, Префикс)
    // Если здесь происходит рекурсивный вызов или сложная логика 
    // поиска кода вручную, это может привести к зависанию.
    Если ТипЗнч(ЭтотОбъект.Код) = Тип("Строка") Тогда
        // Старая логика, которая больше не актуальна для числового кода
    КонецЕсли;
КонецПроцедуры

Шаг 2. Исследуем работу СУБД через технологический журнал

Если программный код чист, нам необходимо понять, на каком этапе «спотыкается» SQL-сервер. Для этого проанализируем лог технологического журнала. Типичная последовательность команд при генерации кода выглядит следующим образом:

  1. Старт транзакции: BEGIN TRANSACTION.
  2. Установка блокировки на таблицу ресурсов: Regions=ReferenceX.REFLOCK, Locks='ReferenceX.REFLOCK Exclusive'.
  3. Поиск максимального значения:
    
    SELECT MAX(T1._Code)
    FROM _Reference142 T1
    
  4. Вставка новой записи с полученным кодом.

Разберем ситуацию: если в колонке _Code остались данные, которые некорректно преобразовались из строки в число (например, содержали лидирующие пробелы или спецсимволы), функция MAX() может выполняться крайне медленно, вызывая Full Table Scan. В этом случае мы увидим в ТЖ событие DBV8DBPostgreSQL или DBMSSQL с длительным временем выполнения и последующим TTIMEOUT.

Шаг 3. Сброс сервиса нумерации и перезагрузка кластера

Как показывает практика (сообщение 5 и 6 форума), самым быстрым решением часто является рестарт службы кластера серверов 1С:Предприятия. Это необходимо для полной очистки кэша сервиса нумерации.

Однако, если перезагрузка всего кластера невозможна (рабочая база с множеством пользователей), попробуем применить «мягкий» способ сброса нумерации:

  1. Зайдем в конфигуратор и временно отключим автонумерацию у справочника.
  2. Сохраним конфигурацию базы данных.
  3. Запустим сеанс «1С:Предприятие» и попробуем записать один элемент с кодом, введенным вручную.
  4. Вернемся в конфигуратор, включим автонумерацию обратно и снова обновим конфигурацию.

Этот цикл действий заставляет платформу обновить записи в системных таблицах (таких как _Numbering), которые отвечают за хранение последнего выданного номера.

Шаг 4. Очистка «фантомных» данных в таблице СУБД

Проанализируем состояние данных в таблице справочника. Даже если через интерфейс 1С справочник кажется пустым, в базе данных могут существовать «битые» записи. Выясним причину, выполнив запрос через консоль запросов 1С с установленным флагом «Выбирать удаленные» (если используется механизм удаления объектов) или напрямую через SQL Management Studio.

Проверим наличие записей, где код не может быть приведен к числу. Рассмотрим пример SQL-запроса для поиска таких проблемных мест (для MS SQL):


SELECT _IDRRef, _Code 
FROM _Reference142 
WHERE ISNUMERIC(_Code) = 0

Если такие записи найдены, их необходимо либо удалить, либо исправить их код на корректное числовое значение. После внесения изменений обязательно выполним обновление статистики и реиндексацию таблицы в СУБД. Это критически важно, так как старые индексы, построенные для строковых данных, могут мешать оптимизатору запросов после смены типа колонки на числовой.

Шаг 5. Тестирование и исправление (ТиИ)

Финальным этапом восстановления нормальной работы справочника будет запуск штатной процедуры «Тестирование и исправление». В окне настройки выберем следующие пункты:

Важный момент: если база файловая, перед запуском ТиИ обязательно воспользуемся утилитой chdbfl.exe, которая проверит физическую целостность файла 1Cv8.1CD. При смене типов данных физическая структура таблицы могла быть повреждена, что и вызывает зависание при попытке записи.

Резюме и рекомендации

Подводя итог, можно сказать, что зависание при вызове УстановитьНовыйКод() — это комплексная проблема, возникающая на стыке кэширования платформы и производительности СУБД.

Рассмотрим краткий алгоритм действий при возникновении подобной ситуации:

  1. Убедимся в отсутствии бесконечных циклов в коде ПриУстановкеНовогоКода и подписках.
  2. Перезагрузим рабочие процессы или весь кластер серверов 1С для сброса кэша нумерации.
  3. Проверим таблицу справочника на наличие некорректных (нечисловых) данных в поле Код.
  4. Выполним обновление статистики и реиндексацию средствами SQL или через ТиИ 1С.

Соблюдение этой последовательности позволит избежать использования «костылей» в коде и вернет штатную работу механизма автонумерации справочника.

← На главную