Почему при проведении документов в 1С возникает конфликт блокировок во время синхронизации и как это исправить

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

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

Суть проблемы и природа таблиц __NODE

Для начала проанализируем техническую сторону вопроса. Когда в конфигурации настроен план обмена, платформа 1С для каждого узла создает служебную таблицу в базе данных СУБД (например, MS SQL Server). Эти таблицы имеют префикс __NODE (например, __NODE27). Их основная задача — хранить регистрацию изменений объектов.

Разберем, что происходит в момент конфликта:

  1. При проведении документа: Платформа пытается записать данные в таблицу регистрации изменений __NODE для всех узлов, в которые этот документ должен быть выгружен. Это происходит внутри транзакции проведения.
  2. При синхронизации: Процесс обмена считывает данные из этой же таблицы __NODE и, после успешной отправки пакета, удаляет записи из неё.

Конфликт возникает из-за того, что процесс обмена накладывает блокировку на всю таблицу регистрации для обеспечения целостности данных при чтении и удалении. Если транзакция обмена длится слишком долго, попытка провести документ завершается ошибкой по таймауту. Раньше система могла "подвисать" и ждать, так как время выполнения обмена укладывалось в стандартный таймаут установки блокировки (обычно 20 секунд). Как только объем данных или время доступа к диску (в случае с Яндекс.Диском) увеличились, ожидание стало превышать этот порог, что привело к выбросу ошибки.

Решение 1: Настройка режима RCSI на стороне SQL-сервера

Одним из самых эффективных системных способов решения проблемы блокировок "чтение против записи" является включение режима Read Committed Snapshot Isolation (RCSI) в MS SQL Server.

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

Для включения этого режима (требуется монопольный доступ к базе) используйте следующий скрипт:


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

Решение 2: Программная реализация очереди ожидания

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


ПопыткаПроведения = Ложь;
КоличествоПопыток = 0;
МаксПопыток = 5;

Пока НЕ ПопыткаПроведения И КоличествоПопыток < МаксПопыток Цикл
    Попытка
        КоличествоПопыток = КоличествоПопыток + 1;
        ЭтотОбъект.Записать(РежимЗаписиДокумента.Проведение);
        ПопыткаПроведения = Истина;
    Исключение
        ОписаниеОшибки = ИнформацияОбОшибке().Описание;
        Если Найти(ОписаниеОшибки, "Конфликт блокировок") > 0 Тогда
            // Если возникла блокировка, ждем 2 секунды перед следующей попыткой
            // В управляемом приложении можно использовать фоновое задание или таймаут
            // Для упрощения примера используем задержку через КомандаСистемы
            КомандаСистемы("timeout /t 2 /nobreak > nul"); 
        Иначе
            ВызватьИсключение; // Если ошибка не связана с блокировкой, пробрасываем её дальше
        КонецЕсли;
    КонецПопытки;
КонецЦикла;

Решение 3: Использование флага "Идет синхронизация"

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

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

Решение 4: Оптимизация порций данных и транзакций обмена

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

Мы можем уменьшить размер порции данных при выгрузке. Для этого в коде модуля обмена или в правилах обмена следует ограничить количество объектов, обрабатываемых за один проход. Например, вместо 10 000 объектов за раз, настроим выгрузку порциями по 500. Таким образом, между транзакциями обмена будут появляться "окна", в которые SQL-сервер сможет пропустить транзакции проведения документов от пользователей.

Также проверьте параметр ПараметрыОбменаДанными.ВыгружатьОбъектыПорциями. В современных версиях УТ 11 это позволяет значительно снизить нагрузку на таблицу __NODE.

Решение 5: Уход от прямой записи на Яндекс.Диск

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

  1. 1С блокирует файл для записи.
  2. Агент Яндекс.Диска пытается заблокировать файл для чтения и отправки в облако.

Это затягивает время выполнения транзакции 1С. Рекомендуем сначала выполнять выгрузку в локальную временную папку на быстром диске (SSD), а после завершения выгрузки и закрытия транзакции в 1С, копировать готовый файл в папку синхронизации Яндекс.Диска средствами операционной системы.

Заключение

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

← На главную