При работе с крупными инсталляциями 1С:ERP Управление предприятием пользователи и администраторы часто сталкиваются с ситуацией, когда в мониторе Закрытия месяца внезапно появляются ошибки блокировок, хотя само закрытие никто не запускал. Особенно остро это проявляется при выполнении масштабных операций с нормативно-справочной информацией (НСИ), таких как удаление десятков тысяч позиций справочника Номенклатура. Рассмотрим подробнее, почему система блокирует прошлые периоды и как правильно организовать процесс массовой очистки данных, чтобы не парализовать работу базы.
Первым делом проанализируем, почему ошибки возникают даже тогда, когда интерактивный процесс закрытия месяца не запущен. В современных версиях ERP за актуальностью данных следит специальное регламентное задание — Обновление состояний закрытия месяца. Это задание работает в фоновом режиме практически непрерывно. Его основная задача — мониторинг изменений в регистрах и справочниках для определения того, какие этапы (например, «Расчет себестоимости» или «Формирование движений по партиям») требуют пересчета.
Когда мы инициируем массовое удаление объектов, система контроля ссылочной целостности начинает искать связи удаляемой номенклатуры во всей базе данных. Как только механизм мониторинга фиксирует попытку изменения или удаления записи, которая потенциально влияет на финансовый результат прошлых периодов, он пытается записать информацию об этом в служебные таблицы. В частности, страдает регистр сведений Задания к расчету.
В архитектуре 1С:ERP учет номенклатуры реализован через промежуточные справочники-ключи. Рассмотрим это на примере объекта Ключи аналитики учета номенклатуры. Почти каждая проводка или запись в регистре накопления ссылается не на саму номенклатуру, а на идентификатор этой аналитики. При удалении 100 000 позиций справочника Номенклатура система обязана:
При таком объеме данных происходит так называемая эскалация блокировок. Вместо того чтобы блокировать отдельные строки, СУБД (например, MS SQL Server или PostgreSQL) блокирует целые страницы данных или даже всю таблицу целиком. В этот же момент фоновое задание Обновление состояний закрытия месяца пытается прочитать эти таблицы, чтобы обновить статус этапов. Возникает классический Deadlock (взаимная блокировка), который пользователь видит как ошибку в интерфейсе закрытия месяца.
Многие удивляются, почему при удалении данных в текущем году ошибки выпадают на периоды двух- или трехлетней давности (например, 2019–2020 гг.). Причина кроется в том, что стандартный механизм поиска ссылок в 1С не ограничен датой. Если удаляемая номенклатура хотя бы раз фигурировала в документах 2019 года, система регистрации изменений пометит этот месяц как «требующий пересчета». Таким образом, массовая очистка справочника превращается в глобальный процесс пересмотра актуальности всей истории учета в базе.
Для успешного выполнения массовых операций и предотвращения блокировок мы рекомендуем использовать комплексный подход.
Самый надежный способ — исключить конкуренцию процессов. Если вам необходимо удалить 100 000 объектов, это следует делать в технологическое окно (выходные или ночное время). Рассмотрим, как минимизировать риски:
/AllowExecuteScheduledJobs –Off. Это полностью запретит выполнение любых фоновых заданий, включая мониторинг закрытия месяца.Если полностью остановить сервер невозможно, проанализируем настройки самой программы. В разделе НСИ и администрирование найдите настройки закрытия месяца. Там присутствует опция «Выполнять регламентные операции закрытия месяца в фоне». Ее необходимо отключить на время проведения массовых корректировок НСИ. Это снизит интенсивность обращений системы к регистру заданий.
Если вы уверены, что удаляемая номенклатура была загружена ошибочно и не имеет движений (ссылок), можно использовать программный метод удаления. Это значительно быстрее, так как не вызывает стандартный механизм поиска ссылок через интерфейс. Посмотрим на пример кода, который может использовать программист:
// Пример программного удаления без проверки ссылок (использовать с осторожностью!)
ОбъектНоменклатура = Справочники.Номенклатура.НайтиПоКоду("00001").ПолучитьОбъект();
Если ОбъектНоменклатура <> Неопределено Тогда
ОбъектНоменклатура.ОбменДанными.Загрузка = Истина; // Отключаем стандартные проверки
ОбъектНоменклатура.Удалить();
КонецЕсли;
Установка флага ОбменДанными.Загрузка = Истина позволяет избежать срабатывания части подписок на события, которые могут инициировать обновление состояний закрытия месяца.
После завершения удаления вы можете обнаружить, что все прошлые месяцы стали «красными» (требуют пересчета). Чтобы не пересчитывать 2019 год заново, проанализируем состояние регистра Задания к расчету. Если вы точно знаете, что удаление не затронуло реальные финансовые показатели (например, удалялись только карточки без остатков), записи в этом регистре можно очистить программно. Рассмотрим, как это сделать:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ЗаданияКРасчету.Период КАК Период,
| ЗаданияКРасчету.Регистратор КАК Регистратор
|ИЗ
| РегистрСведений.ЗаданияКРасчету КАК ЗаданияКРасчету
|ГДЕ
| ЗаданияКРасчету.Месяц < &ДатаГраницы";
Запрос.УстановитьПараметр("ДатаГраницы", '20230101'); // Укажите нужную дату
// Далее следует логика очистки найденных записей
Важно: Очистка регистра Задания к расчету — это крайняя мера. Она требует полного понимания того, что целостность данных не нарушена. После очистки обязательно проверьте отчет «Контроль актуальности закрытия месяца».
Подводя итог, отметим: конфликт блокировок в данном случае — это не ошибка программы, а следствие работы механизмов контроля целостности. Планируйте массовые изменения НСИ заранее, отключайте фоновые процессы и используйте монопольный режим доступа к базе данных.