Как устранить конфликт блокировок при выполнении транзакции в 1С 8.3?

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

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

Выясним причину возникновения конфликтов

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

Рассмотрим подробнее типичные сценарии, приводящие к конфликту:

  1. Длительные транзакции: когда внутри одной транзакции выполняется слишком много действий (чтение, расчеты, запись нескольких документов).
  2. Неоптимальные запросы: отсутствие индексов заставляет СУБД сканировать всю таблицу, блокируя ее целиком.
  3. Порядок обращения к объектам: если два разных процесса обращаются к одним и тем же таблицам в разном порядке, возникает Deadlock (взаимная блокировка).

Переход на режим управляемых блокировок

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

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


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

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

Оптимизация кода внутри транзакции

Посмотрим на пример того, как неправильное чтение данных может вызвать проблему. Часто разработчики используют запрос внутри цикла или читают данные, которые им не нужны для текущей операции. Мы рекомендуем следовать правилу: «Блокируй как можно позже, отпускай как можно раньше».

Проанализируем шаги по оптимизации кода:

  1. Вынесите все тяжелые расчеты за пределы транзакции (до метода Записать()).
  2. Используйте МенеджерВременныхТаблиц для подготовки данных, чтобы основной запрос к реальным таблицам БД выполнялся максимально быстро.
  3. Проверьте, установлены ли индексы на поля, которые используются в условиях ГДЕ и СВЯЗИ.

Рассмотрим пример правильной подготовки данных перед записью:


// Сначала готовим данные во временной таблице
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
Запрос.Текст = "ВЫБРАТЬ * ПОМЕСТИТЬ ВТ_Данные ИЗ &ТаблицаЗначений КАК ТЗ";
Запрос.УстановитьПараметр("ТаблицаЗначений", ТЗ_Списания);
Запрос.Выполнить();

// Начинаем транзакцию только перед записью
НачатьТранзакцию();
Попытка
    // Устанавливаем управляемую блокировку
    Блокировка = Новый БлокировкаДанных;
    // ... описание блокировки ...
    Блокировка.Заблокировать();
    
    // Выполняем запись
    Объект.Записать();
    ЗафиксироватьТранзакцию();
Исключение
    ОтменитьТранзакцию();
    ВызватьИсключение;
КонецПопытки;

Поиск «виновника» блокировки

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

Разберем алгоритм поиска:

Также полезно использовать технологический журнал (ТЖ). Настроим сбор событий TLOCK, чтобы увидеть подробности: имя таблицы, тип блокировки и контекст кода (стек вызова), который ее вызвал. Это позволит нам точно определить место в коде, требующее оптимизации.

Работа с индексами в SQL

Иногда причина конфликта кроется не в коде 1С, а в том, как СУБД интерпретирует запрос. Если поле не индексировано, SQL Server может применить Lock Escalation (укрупнение блокировки) до уровня страницы или всей таблицы.

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

  1. Все поля, входящие в условия соединений запросов, должны иметь индексы.
  2. Для регистров сведений убедитесь, что измерения расположены в правильном порядке (наиболее селективные — первыми).
  3. Регулярно проводите обслуживание базы данных: обновление статистики и дефрагментацию индексов.

Важный момент: в 1С 8.3 при использовании управляемых блокировок система сама старается минимизировать уровень блокировок в СУБД до Read Committed, что значительно снижает вероятность конфликтов по сравнению с автоматическим режимом (где используется Repeatable Read или Serializable).

Заключение и выводы

Мы проанализировали основные причины возникновения ошибок «Конфликт блокировок» и рассмотрели способы их решения. Подведем итоги нашей совместной работы:

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

← На главную