Какие блокировки устанавливаются при вызове метода СообщениеXML.НачатьЗапись() и как их воспроизвести при обмене через JSON

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

При реализации механизмов обмена данными в системе «1С:Предприятие» разработчики часто сталкиваются с необходимостью выбора между стандартным форматом XML и более современным/легковесным JSON. Стандартные объекты платформы, такие как ЗаписьСообщенияОбмена, ориентированы на работу с XML и берут на себя значительную часть «магии» по управлению транзакциями и блокировками. Переходя на JSON, мы теряем эту автоматику. В данной статье мы подробно разберем, что именно происходит «под капотом» метода НачатьЗапись() и как правильно воссоздать это поведение в собственных механизмах обмена.

Анализируем суть блокировки метода НачатьЗапись()

Многие разработчики опасаются, что вызов СообщениеXML.НачатьЗапись() накладывает глобальную блокировку на всю базу данных или на таблицы регистрации изменений. Давайте проанализируем ситуацию и выясним, так ли это на самом деле. На самом деле, платформа действует гораздо точечнее.

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

Это делается для решения двух ключевых задач:

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

Разберем механизм управления транзакциями

Рассмотрим подробнее, как НачатьЗапись() взаимодействует с транзакциями базы данных. Этот метод не просто открывает текстовый поток файла, он явно открывает транзакцию. Все действия, которые мы выполняем до вызова ЗакончитьЗапись(), будут находиться внутри этой транзакции.

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

Взаимодействие с таблицами регистрации изменений

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

На самом деле, НачатьЗапись() не блокирует таблицу регистрации изменений. Запись новых изменений пользователями может продолжаться параллельно. Блокировка таблиц изменений происходит кратковременно только в момент вызова метода ПланыОбмена.ВыбратьИзменения(), чтобы получить согласованный «снимок» данных на момент начала выгрузки. Это никак не мешает параллельной работе пользователей.

Реализуем аналогичный механизм для обмена через JSON

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

Нам потребуется использовать объект БлокировкаДанных и явное управление транзакциями. Посмотрим на пример кода:


// 1. Начинаем транзакцию, чтобы обеспечить атомарность
НачатьТранзакцию();

Попытка
    // 2. Устанавливаем управляемую блокировку на узел плана обмена
    Блокировка = Новый БлокировкаДанных;
    ЭлементБлокировки = Блокировка.Добавить("ПланОбмена.СинхронизацияДанныхЧерезУниверсальныйФормат");
    ЭлементБлокировки.УстановитьЗначение("Ссылка", УзелОбмена);
    ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
    Блокировка.Заблокировать();

    // 3. Получаем текущий номер сообщения и инкрементируем его
    // Платформа делает это автоматически в XML, мы делаем вручную
    НовыйНомерОтправленного = УзелОбмена.НомерОтправленного + 1;

    // 4. Подготавливаем запись JSON
    ЗаписьJSON = Новый ЗаписьJSON;
    ЗаписьJSON.ОткрытьФайл(ИмяФайла);
    ЗаписьJSON.ЗаписатьНачалоОбъекта();
    ЗаписьJSON.ЗаписатьИмяСвойства("НомерСообщения");
    ЗаписьJSON.ЗаписатьЗначение(НовыйНомерОтправленного);

    // 5. Выбираем изменения
    Выборка = ПланыОбмена.ВыбратьИзменения(УзелОбмена, НовыйНомерОтправленного);

    // Здесь реализуем цикл записи объектов в JSON
    Пока Выборка.Следующий() Цикл
        // Сериализация объекта в JSON
    КонецЦикла;

    ЗаписьJSON.ЗаписатьКонецОбъекта();
    ЗаписьJSON.Закрыть();

    // 6. Обновляем номер в узле (имитация поведения платформы)
    ОбъектУзла = УзелОбмена.ПолучитьОбъект();
    ОбъектУзла.НомерОтправленного = НовыйНомерОтправленного;
    ОбъектУзла.Записать();

    // 7. Фиксируем транзакцию
    ЗафиксироватьТранзакцию();
Исключение
    ОтменитьТранзакцию();
    // Обработка ошибки
КонецПопытки;

Проанализируем влияние на производительность

Выясним, почему стандартный обмен иногда «тормозит» систему. Как мы уже поняли, проблема не в самом методе НачатьЗапись(), а в длительности транзакции. Если между НачатьЗапись() и ЗакончитьЗапись() (или в нашем случае — внутри ручной транзакции) выполняется сложная обработка данных, которая длится десятки минут, то узел плана обмена будет заблокирован всё это время.

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

Подведем итоги

Переход на JSON не означает потерю надежности, если понимать принципы работы платформы. Рассмотрим ключевые выводы:

Используя приведенную выше схему с ручным управлением блокировками, вы сможете создать надежную систему обмена через JSON, которая будет работать так же стабильно, как и стандартные механизмы 1С.

← На главную