Почему расчет себестоимости в УПП вызывает блокировки даже вне транзакции и как это исправить

Программист 1С v8.3 (Обычные формы) Бухгалтерский учет Промышленность, строительство и АПК
← На главную

Работа с крупными информационными базами «1С:Управление производственным предприятием» (УПП) объемом более 500–800 Гб накладывает особые требования к выполнению регламентных операций. Одной из самых ресурсоемких задач является Расчет себестоимости выпуска (РСВ). Часто системные администраторы и программисты сталкиваются с ситуацией, когда даже запуск РСВ в режиме «вне транзакции» не спасает от конфликтов блокировок, мешая оперативной работе пользователей. Разберем подробно, почему это происходит и какие шаги необходимо предпринять для решения проблемы.

Анализируем механизм режима «вне транзакции»

Для начала проанализируем, что на самом деле делает флаг «Выполнять расчет вне транзакции» в документе РегламентнаяОперация. Многие ошибочно полагают, что этот режим полностью отключает механизм блокирования данных. Однако это не так. В обычном режиме РСВ пытается выполнить все расчеты и записи в рамках одной гигантской транзакции. Если расчет длится 5 часов, то все это время данные будут заблокированы.

В режиме «вне транзакции» система разбивает процесс на множество мелких этапов. Однако запись каждого конкретного набора записей в регистры (например, в РегистрБухгалтерии) все равно происходит внутри транзакции. Вызов метода Записать() объекта РегистрБухгалтерииНаборЗаписей инициирует транзакцию на уровне СУБД. Если набор записей содержит тысячи строк, блокировка становится ощутимой для других сеансов.

Выясняем причины блокировки документов «будущего периода»

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

  1. Эскалация блокировок в MS SQL Server. Когда количество мелких блокировок строк (Row Locks) в рамках одной транзакции превышает порог (обычно 5000), SQL Server в целях экономии оперативной памяти заменяет их на одну блокировку всей таблицы (TABLOCK). В этот момент любое обращение к РегиструБухгалтерии, даже по другому периоду, будет ждать завершения расчета.
  2. Блокировка диапазонов (Range Locks). Если конфигурация работает в режиме автоматических блокировок (что характерно для УПП), SQL Server использует уровень изоляции Serializable. Это заставляет СУБД блокировать не только существующие записи, но и диапазоны индексов, чтобы предотвратить появление «фантомных» записей. Если физически данные за разные месяцы расположены на соседних страницах индекса, они будут заблокированы совместно.
  3. Обновление итогов. При записи в регистр бухгалтерии платформа 1С выполняет пересчет итогов. Если система считает, что итоги за будущие периоды могут измениться, она накладывает блокировки на таблицы итогов, которые являются общими для всех периодов.

Способ 1: Использование РИБ для выноса расчета в отдельную базу

Рассмотрим один из самых эффективных архитектурных способов — создание узла Распределенной Информационной Базы (РИБ). Это позволяет полностью изолировать процесс расчета от оперативной работы пользователей.

Посмотрим на алгоритм действий:

  1. Создаем подчиненный узел РИБ, в который передаются только необходимые для расчета данные.
  2. Выполняем расчет себестоимости в этом узле в любое удобное время, не опасаясь блокировок в основной базе.
  3. После завершения расчета выгружаем результат (документ РСВ и его движения) обратно в центральный узел.
Этот метод требует настройки синхронизации, но он гарантирует 100% доступность основной базы для пользователей в режиме 24/7.

Способ 2: Оптимизация на уровне СУБД и платформы

Если вариант с РИБ слишком сложен, проанализируем технические настройки сервера. Для снижения вероятности конфликтов при выполнении РегистрБухгалтерииНаборЗаписей.Записать() выполним следующие шаги:

Настройка MAXDOP. Установим параметр Max Degree of Parallelism в значение 1 на уровне SQL Server. Это предотвратит ситуацию, когда одна тяжелая транзакция записи РСВ захватывает все ядра процессора и вызывает взаимоблокировки (Deadlocks) при параллельном чтении данных другими пользователями.

Обслуживание индексов. Перед расчетом себестоимости крайне важно выполнить дефрагментацию или перестроение индексов по регистру бухгалтерии и регистру накопления «Затраты». Высокая фрагментация заставляет SQL Server чаще прибегать к сканированию всей таблицы вместо поиска по индексу, что мгновенно ведет к эскалации блокировок.

Рассмотрим пример кода, который может быть полезен при программном управлении блокировками, если вы решитесь на доработку модуля ПроцедурыРасчетаСебестоимостиВыпуска:


// Пример установки управляемой блокировки перед записью набора (если режим базы позволяет)
Блокировка = Новый БлокировкаДанных;
ЭлементБлокировки = Блокировка.Добавить("РегистрБухгалтерии.Хозрасчетный");
ЭлементБлокировки.УстановитьЗначение("Период", Новый Диапазон(ДатаНачала, ДатаОкончания));
ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
Блокировка.Заблокировать();

Способ 3: Организационные меры и дробление задач

Проанализируем возможность сокращения объема данных, обрабатываемых за один раз. В УПП расчет себестоимости можно запускать по отдельным этапам. Вместо одного общего запуска, разберем по шагам выполнение регламентных операций:

Выполняя эти этапы последовательно с небольшими паузами, мы даем возможность SQL Server «отпустить» блокировки и обработать очередь запросов от производственных документов пользователей. Также рекомендуется перенести выполнение наиболее тяжелых этапов на ночное время, используя планировщик задач.

Заключение

Блокировки при расчете себестоимости в УПП на базе 800 Гб — это не ошибка программы, а следствие естественных ограничений СУБД при работе с огромными массивами данных в автоматическом режиме блокировок. Для стабильной работы рекомендуем сочетать регулярное обслуживание индексов SQL, настройку MAXDOP и, при необходимости, вынос расчета в отдельный узел РИБ. Это позволит сохранить высокую производительность системы даже при интенсивной работе пользователей в будущих периодах.

← На главную