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

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

При работе с типовыми модулями интеграции «1С-Битрикс» и крупными конфигурациями, такими как УТ 11.4 или ERP, программисты часто сталкиваются с ошибкой Конфликт блокировок при выполнении транзакции. Ошибка сопровождается сообщением от SQL Server: Lock request time out period exceeded. Рассмотрим подробнее, почему возникает эта ситуация, проанализируем механизмы работы модуля обмена и разберем конкретные шаги по исправлению данной проблемы.

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

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

На уровне СУБД этот метод инициирует запись в таблицу изменений (обычно это таблица с окончанием _ChngR). Если в системе одновременно работают десятки пользователей или выполняются фоновые задания, несколько транзакций пытаются одновременно наложить исключительную блокировку (X-lock) на одни и те же ресурсы таблицы изменений. Ситуация усугубляется, если транзакция проведения документа длительная — пока 1С рассчитывает себестоимость или проверяет остатки, блокировка на узле обмена удерживается, заставляя другие сеансы ждать, пока не истечет время ожидания (timeout).

Решение 1: Проверка наличия объекта в плане обмена перед регистрацией

Это самый эффективный и быстрый способ «вылечить» блокировки без кардинальной переработки модуля. Как правило, модуль Битрикса регистрирует изменения «на каждый чих». Если объект уже зарегистрирован на узле, повторный вызов ЗарегистрироватьИзменения всё равно создает транзакционную нагрузку. Нам нужно добавить проверку: если объект уже ждет выгрузки, регистрировать его повторно не нужно.

Разберем, как это реализовать. Вместо прямого вызова типового кода регистрации, создадим свою функцию-обертку. Рассмотрим пример кода, который можно внедрить в общий модуль Б_ОбменССайтомСервер или использовать через расширение:


Функция НужноЛиРегистрироватьИзменение(Узел, Ссылка) Экспорт
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ ПЕРВЫЕ 1
        |   Истина КАК Зарегистрировано
        |ИЗ
        |   ПланОбмена.Б_ОбменССайтом.Изменения КАК ТаблицаИзменений
        |ГДЕ
        |   ТаблицаИзменений.Узел = &Узел
        |   И ТаблицаИзменений.Ссылка = &Ссылка";
    
    Запрос.УстановитьПараметр("Узел", Узел);
    Запрос.УстановитьПараметр("Ссылка", Ссылка);
    
    Выборка = Запрос.Выполнить().Выбрать();
    Возврат НЕ Выборка.Следующий(); // Если записи нет, значит нужно регистрировать
КонецФункции

Теперь в местах вызова ПланыОбмена.ЗарегистрироватьИзменения(МассивУзловТовары, Запись.Номенклатура) мы добавляем условие:


Для Каждого Узел Из МассивУзловТовары Цикл
    Если НужноЛиРегистрироватьИзменение(Узел, Запись.Номенклатура) Тогда
        ПланыОбмена.ЗарегистрироватьИзменения(Узел, Запись.Номенклатура);
    КонецЕсли;
КонецЦикла;

Этот подход позволяет избежать избыточных обращений к таблице изменений SQL Server, существенно снижая вероятность конфликтов блокировок.

Решение 2: Вынос регистрации изменений за пределы основной транзакции

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

Разберем этот алгоритм по шагам:

  1. Создаем новый регистр сведений ОчередьРегистрацииБитрикс с единственным измерением Объект (тип ЛюбаяСсылка).
  2. В модуле Битрикса, в местах регистрации изменений, заменяем вызов ПланыОбмена.ЗарегистрироватьИзменения на простую запись в наш новый регистр. Запись в плоский регистр происходит значительно быстрее, чем работа с таблицей изменений плана обмена.
  3. Создаем регламентное задание, которое раз в 5–10 минут считывает данные из ОчередьРегистрацииБитрикс, пачками регистрирует их на узлах плана обмена и очищает регистр.

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

Решение 3: Оптимизация настроек MS SQL Server

Иногда корень проблемы кроется в настройках СУБД. Проанализируем параметры сервера. Для высоконагруженных баз 1С на MS SQL Server крайне рекомендуется включение режима RCSI (Read Committed Snapshot Isolation).

Этот режим позволяет операциям чтения не блокироваться операциями записи. Для этого выполним следующие SQL-команды (предварительно переведя базу в Single User mode):


ALTER DATABASE [ИмяВашейБазы] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
ALTER DATABASE [ИмяВашейБазы] SET READ_COMMITTED_SNAPSHOT ON;
ALTER DATABASE [ИмяВашейБазы] SET MULTI_USER;

Также проверим параметр MAXDOP (Maximum Degree of Parallelism). Для 1С рекомендуется устанавливать значение 1, чтобы предотвратить распараллеливание запросов, которое часто приводит к сложным взаимоблокировкам (Deadlocks) в таблицах изменений.

Анализ избыточности выгрузки

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

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

Резюме: Чтобы навсегда избавиться от блокировок в связке 1С и Битрикс, необходимо комбинировать программные методы (проверка на дубли в плане обмена) и инфраструктурные настройки (RCSI на SQL Server). Это обеспечит стабильную работу системы даже при больших объемах номенклатуры и интенсивном документообороте.

← На главную