Почему возникает ошибка вызова управляемой блокировки внутри автоматической транзакции в 1С?

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

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

«Использование блокировки допустимо только внутри транзакции в режиме управляемых блокировок!»

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

Причина конфликта в типовом коде и поведении платформы

Разберем архитектурные особенности платформы «1С:Предприятие» и типовых решений, которые приводят к возникновению этой ошибки.

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

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

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


Если глЗначениеПеременной("ИспользоватьБлокировкуДанных") Тогда
    // Вызов установки управляемых блокировок
КонецЕсли;

Инициализация этой переменной в общем модуле ОбщегоНазначения выглядит следующим образом:


Метаданные.РежимУправленияБлокировкойДанных <> Метаданные.СвойстваОбъектов.РежимУправленияБлокировкойДанныхПоУмолчанию.Автоматический

Разработчики типового кода рассчитывали на бинарное состояние: конфигурация работает либо целиком в автоматическом режиме, либо целиком в управляемом. Как только в корне конфигурации выставляется «Автоматический и управляемый», условие неравенства дает Истина. В результате типовой код (например, алгоритм регистрации движений по последовательностям) решает, что управляемые блокировки включены для всей базы, и выполняет вызов Заблокировать() внутри автоматической транзакции проведения документа.

Способ 1. Возврат корневого свойства в автоматический режим

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

  1. Откроем свойства корневого узла конфигурации.
  2. Найдем свойство Режим управления блокировкой данных.
  3. Установим значение «Автоматический».
  4. Обновим конфигурацию базы данных.

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

Способ 2. Корректировка проверки в общем модуле

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

Перейдем в общий модуль ОбщегоНазначения в функцию ПолучитьЗначениеПеременной. Заменим проверку неравенства на строгое равенство управляемому режиму:


// Управляемые блокировки включаем программно только при полном переводе конфигурации
НайденноеЗначение = (Метаданные.РежимУправленияБлокировкойДанных = Метаданные.СвойстваОбъектов.РежимУправленияБлокировкойДанныхПоУмолчанию.Управляемый);

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

Способ 3. Корректный точечный перевод цепочки объектов в управляемый режим

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

  1. Откроем свойства документа, вызывающего ошибку, и установим Режим управления блокировкой данных = «Управляемый».
  2. Проверим все регистры (накопления, сведений, бухгалтерии), по которым данный документ формирует движения при проведении. Для каждого из них в свойствах установим режим «Управляемый».
  3. Обязательно проверим объект «Последовательность», в которую входит проводимый документ. В ветке Последовательности дерева метаданных найдем соответствующий объект (например, РасчетыПоПриобретениюОрганизации) и также установим для него режим «Управляемый».
  4. Проанализируем модуль объекта документа. Если в коде присутствуют явные вызовы начала транзакции, укажем управляемый режим в явном виде: НачатьТранзакцию(РежимУправленияБлокировкойДанных.Управляемый);
  5. Убедимся, что перед чтением и записью данных в процедуре ОбработкаПроведения создаются и накладываются необходимые экземпляры объекта БлокировкаДанных.

Способ 4. Полный перевод конфигурации на управляемые блокировки

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

  1. С помощью групповой обработки метаданных установим свойство Режим управления блокировкой данных в значение «Управляемый» для всех объектов: справочников, документов, регистров, планов счетов, планов видов характеристик и последовательностей.
  2. В корне конфигурации установим свойство Режим управления блокировкой данных в значение «Управляемый».
  3. В настройках базы данных на MS SQL Server включим версионирование строк, выполнив команды:
    
    ALTER DATABASE [ИмяБазы] SET READ_COMMITTED_SNAPSHOT ON WITH ROLLBACK IMMEDIATE;
    ALTER DATABASE [ИмяБазы] SET ALLOW_SNAPSHOT_ISOLATION ON;
    
  4. Проверим корректность проведения основных документов и работы регламентных заданий.

Такой подход полностью исключит рассинхронизацию между транзакциями платформы и логикой типового кода конфигурации.

← На главную