Почему при отключении итогов регистра накопления возникают блокировки и как это решить

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

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

Анализируем причину блокировки системных таблиц

Первым делом проанализируем ситуацию, связанную с поведением самой платформы. Когда мы отключаем итоги у регистра (будь то остатки или обороты), платформа меняет режим работы с таблицами этого регистра в базе данных. Выясним причину, по которой это вызывает конфликты. В структуре хранения 1С существует специальная системная таблица (в MS SQL Server это часто AccumRegOptions или аналогичные внутренние структуры для других СУБД), где хранится информация о текущем состоянии итогов: период рассчитанных итогов, флаг их использования и разделения.

Рассмотрим механизм обращения к этой таблице. Когда итоги включены, платформа эффективно кэширует эти настройки. Но при отключенных итогах в ряде версий платформы (особенно замечено в ветках 8.3.18–8.3.22) при каждой попытке записи набора записей в рамках транзакции платформа инициирует проверку состояния регистра. В этот момент накладывается управляемая блокировка на запись в системной таблице настроек. Поскольку все параллельные потоки пытаются проверить статус одного и того же регистра, они выстраиваются в очередь к одному общему ресурсу — строке настроек регистра в системной таблице. Это и вызывает полную остановку параллельной работы, даже если сами документы пишут данные по совершенно разным измерениям и не пересекаются в таблице движений.

Влияние свойства Удалять автоматически на эскалацию блокировок

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

  1. Режим "Удалять автоматически" включен: Платформа при начале проведения (в событии ОбработкаПроведения) неявно выполняет удаление всех существующих движений этого документа по всем регистрам. Если итоги включены, система использует оптимизированные механизмы. Если же итоги отключены, платформа выполняет прямой SQL-запрос DELETE из физической таблицы движений по регистратору.
  2. Проблема эскалации: При массовом параллельном удалении записей из одной таблицы СУБД (например, MS SQL Server) может решить, что блокировать отдельные строки невыгодно, и выполнить Lock Escalation (эскалацию блокировок). В результате блокируется не конкретный набор строк одного документа, а страница данных или вся таблица целиком. Это моментально останавливает все остальные потоки.
  3. Решение: Установим свойство Удалять автоматически в значение "При отмене проведения". В этом случае платформа перестает выполнять неявную очистку при каждом проведении. Теперь программист должен сам управлять наборами записей, но это избавляет нас от избыточных и "грубых" блокировок со стороны СУБД в начале транзакции.

Роль механизма Разделения итогов

Проанализируем, почему включение итогов "лечит" проблему. В платформе 1С реализован механизм Разделения итогов (Split Totals). Он создан специально для того, чтобы при записи в одну и ту же "точку" (одинаковый период и набор измерений) разные сеансы не блокировали друг друга. Платформа создает несколько записей в таблице итогов вместо одной, распределяя нагрузку.

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

Практические способы обхода проблемы

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

Способ 1. Использование свойства Активность

Этот метод позволяет "обмануть" систему, выполняя запись в несколько этапов:

  1. Оставляем итоги включенными.
  2. Проводим документы или записываем наборы записей в параллельных потоках, устанавливая свойство Активность = Ложь.
  3. 
    НаборЗаписей = РегистрыНакопления.ВашРегистр.СоздатьНаборЗаписей();
    НаборЗаписей.Отбор.Регистратор.Установить(СсылкаНаДокумент);
    // ... заполнение движений ...
    Для Каждого Движение Из НаборЗаписей Цикл
        Движение.Активность = Ложь;
    КонецЦикла;
    НаборЗаписей.Записать();
    
  4. Запись неактивных движений не вызывает пересчета итогов, поэтому работает очень быстро и не создает нагрузку на таблицу итогов.
  5. После завершения загрузки выключаем итоги регистра.
  6. В один поток (это важно!) активируем записи и снова включаем итоги.

Способ 2. Режим загрузки данных

Если блокировка возникает из-за платформенных проверок при записи, попробуем использовать свойство ОбменДанными.Загрузка. Это отключает большинство проверок целостности и платформенных обработчиков, которые могут инициировать обращения к системным таблицам настроек.


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

Способ 3. Обновление платформы

Выясним, не имеем ли мы дело с известным багом. Если блокировка происходит именно на системной таблице настроек итогов при их отключенном состоянии, это признанная ошибка платформы. Рекомендуется обновить платформу до актуальных релизов (не ниже 8.3.22.1709, 8.3.23.1688 и выше), где работа с кэшированием состояния итогов была оптимизирована, а избыточные блокировки сняты.

Резюме и выводы

Подведем итог нашему исследованию. Отключение итогов — мощный инструмент оптимизации, но он требует осторожности при параллельной обработке. Если вы столкнулись с блокировками:

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

← На главную