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

Программист IT и автоматизация бизнеса
← На главную

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

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

Анализ причины: почему Прочитать() вызывает блокировку

Проанализируем механику работы платформы при выполнении следующего фрагмента кода:


НаборШаблон = РегистрыСведений.CRM_МаршрутБизнесПроцесса.СоздатьНаборЗаписей();
НаборШаблон.Отбор.БизнесПроцесс.Установить(БизнесПроцесс);
НаборШаблон.Отбор.ТочкаМаршрута.Установить(ТочкаМаршрута);
НаборШаблон.Прочитать();

В режиме управляемых или смешанных блокировок вызов метода Прочитать() у объекта НаборЗаписей автоматически накладывает разделяемую управляемую блокировку (Shared Lock) на устанавливаемый диапазон отбора. Если вызов происходит внутри транзакции (включая неявные транзакции при открытии форм или записи связанных объектов), эта блокировка удерживается до момента завершения транзакции.

Основные причины возникновения ошибок и таймаутов в данном сценарии:

  1. Конфликт смешанного режима: При режиме «Автоматический и управляемый» для объектов с автоматическим режимом СУБД накладывает суровые блокировки на уровне таблиц/диапазонов SQL (уровень изоляции SERIALIZABLE или REPEATABLE READ). Если в одной транзакции пересекаются автоматические и управляемые объекты, возникает двойная нагрузка блокировками.
  2. Эскалация блокировки («Чтение с последующей записью»): Если после вызова метода Прочитать() выполняется очистка или модификация набора с последующей записью, платформа пытается повысить уровень блокировки с разделяемой до исключительной. Если другой параллельный процесс или фоновое задание в этот момент удерживает разделяемую блокировку, возникает таймаут.
  3. Отсутствие версионирования на сервере СУБД: Если на сервере MS SQL Server для базы данных не включен режим Snapshot Isolation, операции чтения продолжают блокировать строки на уровне СУБД.

Вариант 1. Запись набора без предварительного чтения

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

Разберем оптимизированный вариант без чтения:


НаборШаблон = РегистрыСведений.CRM_МаршрутБизнесПроцесса.СоздатьНаборЗаписей();
НаборШаблон.Отбор.БизнесПроцесс.Установить(БизнесПроцесс);
НаборШаблон.Отбор.ТочкаМаршрута.Установить(ТочкаМаршрута);

// Сразу записываем пустой набор с замещением (Истина)
НаборШаблон.Записать(Истина);

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

Вариант 2. Разделение чтения и записи с помощью запросов

Если данные из регистра все же необходимы для выполнения расчетов перед изменением, не следует использовать объектную технику (НаборЗаписей.Прочитать()) в транзакции. Лучше прочитать данные с помощью обычного запроса вне транзакции, а транзакцию открывать только непосредственно для записи изменений.

Посмотрим на пример кода:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	Т.БизнесПроцесс,
    |	Т.ТочкаМаршрута
    |ИЗ
    |	РегистрСведений.CRM_МаршрутБизнесПроцесса КАК Т
    |ГДЕ
    |	Т.БизнесПроцесс = &БизнесПроцесс
    |	И Т.ТочкаМаршрута = &ТочкаМаршрута";

Запрос.УстановитьПараметр("БизнесПроцесс", БизнесПроцесс);
Запрос.УстановитьПараметр("ТочкаМаршрута", ТочкаМаршрута);

Результат = Запрос.Выполнить();
// Выполняем необходимую логику обработки данных...

Вариант 3. Включение версионирования строк в MS SQL Server

Для корректной работы управляемых и смешанных блокировок на СУБД MS SQL Server необходимо включить режим версионирования строк. Это позволит запросам чтения читать прошлые версии данных без наложения S-блокировок на уровне SQL Server.

Для этого в MS SQL Server Management Studio необходимо выполнить команду:


ALTER DATABASE [Имя_Базы_Данных] SET READ_COMMITTED_SNAPSHOT ON WITH ROLLBACK IMMEDIATE;

Важно: Выполнение этой команды требует монопольного доступа к базе данных 1С.

Вариант 4. Полный перевод конфигурации на управляемый режим

Режим «Автоматический и управляемый» является лишь временным шагом при переходе. Он сочетает недостатки обоих механизмов: жесткие блокировки СУБД и накладные расходы менеджера блокировок 1С.

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

← На главную