Почему управляемая блокировка данных в 1С может блокировать лишние данные и как это исправить?

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

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

Постановка задачи и анализ программного кода

Рассмотрим классическую ситуацию: нам необходимо реализовать проведение документа в режиме управляемых блокировок так, чтобы блокировались только те остатки ТМЦ, которые указаны в табличной части текущего документа. Проанализируем типичный фрагмент кода, который используется для этих целей:


Блокировка = Новый БлокировкаДанных;
ЭлементБлокировки = Блокировка.Добавить("РегистрНакопления.ОстаткиТМЦ");
ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;

// Используем таблицу значений как источник данных для блокировки
ЭлементБлокировки.ИсточникДанных = ТЧ_МПЗ;
ЭлементБлокировки.ИспользоватьИзИсточникаДанных("ВариантНоменклатуры", "ВариантНоменклатуры");

Блокировка.Заблокировать;

// Далее следует выполнение запроса и логика списания
ОстаткиПоПартиям = Запрос.Выполнить().Выгрузить();

На первый взгляд, код выглядит безупречно. Мы четко указали пространство блокировки — регистр ОстаткиТМЦ, установили исключительный режим и ограничили область блокировки конкретными значениями измерения ВариантНоменклатуры. Однако при тестировании выясняется странная особенность: если зациклить выполнение этого кода (имитируя долгую транзакцию), другой сеанс не может провести документ даже по совершенно другой номенклатуре. Более того, могут блокироваться даже операции записи в справочниках.

Выяснение причин избыточного блокирования

Проанализируем, что происходит «под капотом» платформы. Когда мы запускаем процедуру ОбработкаПроведения, наше программное управление блокировками — это лишь верхушка айсберга. Существуют так называемые неявные блокировки, которые накладывает сама платформа.

Одной из главных причин, по которой блокировка распространяется на весь регистр или даже на смежные таблицы, является свойство документа «Удалять движения». Рассмотрим два основных варианта этой настройки:

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

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

Влияние на таблицу итогов и эскалация блокировок

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

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

Также не стоит забывать про эскалацию блокировок на уровне SQL-сервера. Если количество удаляемых строк велико, SQL Server может принять решение заблокировать всю страницу (PAGE) или всю таблицу (TABLE), вместо блокировки отдельных строк. В этом случае управляемые блокировки 1С могут показывать, что все в порядке, но на физическом уровне база данных будет «стоять».

Экспериментальное подтверждение и решение проблемы

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

Как правильно настроить документ для высокой параллельности?

Чтобы избежать описанных проблем и заставить управляемые блокировки работать действительно селективно, рекомендуем придерживаться следующего алгоритма:

  1. Измените свойство документа «Удалять движения» на значение «Удалять автоматически при отмене проведения». Это исключит фазу предварительной очистки всех регистров при начале проведения.
  2. Используйте в коде ОбработкаПроведения явную установку блокировок перед чтением остатков, как было показано в первом примере.
  3. Для записи наборов записей используйте режим замещения. Проанализируем пример кода для записи движений:

// В конце процедуры ОбработкаПроведения
Движения.ОстаткиТМЦ.Записывать = Истина;
// Если нужно записать конкретный набор прямо сейчас
Движения.ОстаткиТМЦ.Записать(); 

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

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

Резюме

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

← На главную