Как обойти остановку обработки при возникновении ошибки «Конфликт блокировок» в SQL-версии 1С?

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

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

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

Почему стандартная «Попытка» не перехватывает ошибку SQL?

Разберем природу возникновения проблемы. В старых версиях платформы (8.1, 8.2) или при использовании конфигураций в режиме автоматических блокировок, управление захватом ресурсов в базе данных полностью делегируется MS SQL Server. Когда возникает ситуация дедлока (Deadlock, ошибка 1205) или превышается таймаут ожидания, SQL Server откатывает транзакцию.

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

Решение 1: Использование фоновых заданий (серверный контекст)

Проанализируем самый надежный и современный метод — перенос логики проведения на сторону сервера через механизм фоновых заданий. Главная особенность фонового задания заключается в том, что у него полностью отсутствует пользовательский интерфейс (UI). Физически некому и нигде показать модальное окно «ОК».

Рассмотрим алгоритм реализации:

  1. Создаем общую серверную процедуру, которая будет принимать массив ссылок на документы для проведения.
  2. Внутри процедуры реализуем цикл с обработкой каждого документа в отдельной транзакции.
  3. Запускаем эту процедуру через ФоновыеЗадания.Выполнить().

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


ПараметрыЗадания = Новый Массив;
ПараметрыЗадания.Добавить(МассивСсылок);
ФоновыеЗадания.Выполнить("МойОбщийМодуль.ПровестиДокументыГруппой", ПараметрыЗадания);

В этом случае, если внутри фонового задания возникнет конфликт блокировок SQL, система честно зайдет в блок Исключение. Мы сможем зафиксировать ошибку в журнале регистрации или в специальном логе и продолжить выполнение цикла для следующего документа.

Решение 2: Проведение через COM-соединение

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

Выясним, как это выглядит на практике:


// Устанавливаем соединение с текущей базой
Connector = Новый COMОбъект("V83.COMConnector");
Connection = Connector.Connect("Srvr='ServerName';Ref='BaseName';Usr='Admin';Pwd='123'");

Для Каждого ДокСсылка Из СписокДокументов Цикл
    Попытка
        // Вызываем проведение через COM
        Connection.МойОбщийМодуль.ПровестиДокумент(ДокСсылка);
    Исключение
        ЗаписьЖурналаРегистрации("Ошибка проведения документа: " + ДокСсылка, УровеньЖурналаРегистрации.Ошибка);
    КонецПопытки;
КонецЦикла;

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

Решение 3: Переход на управляемые блокировки

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

Проанализируем преимущества этого подхода:

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

Решение 4: Оптимизация транзакций и группового проведения

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

Разберем правильную структуру цикла проведения:


Для Каждого ДокументОбъект Из Выборка Цикл
    // Каждый документ проводится в своей транзакции
    Попытка
        ДокументОбъект.Записать(РежимЗаписиДокумента.Проведение);
    Исключение
        // Здесь мы ловим ошибки, если они не заблокированы ядром
        Сообщить("Документ " + ДокументОбъект + " не проведен.");
    КонецПопытки;
КонецЦикла;

Важно: не используйте НачатьТранзакцию() перед циклом. Дайте платформе завершать транзакцию после каждого документа. Это значительно снизит нагрузку на MS SQL и уменьшит время удержания блокировок.

Решение 5: Внешний «кликер» на AutoIt (Extreme Way)

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

Пример логики скрипта AutoIt:

  1. Запускаем бесконечный цикл мониторинга процессов 1С.
  2. Если появляется окно с заголовком «1С:Предприятие» и текстом «Конфликт блокировок», скрипт посылает в это окно нажатие клавиши Enter.
  3. Обработка в 1С получает сигнал о закрытии окна и (если она написана правильно) переходит к следующему шагу или перезапускается.

Это «костыльное» решение, но оно эффективно в случаях, когда вмешательство в конфигурацию полностью запрещено регламентами организации.

Рекомендации по настройке SQL Server

Напоследок разберем настройки СУБД, которые помогут снизить частоту появления таких ошибок:

Подведем итог: наиболее стабильным решением является использование фоновых заданий. Это полностью избавляет систему от интерактивности и позволяет коду 1С корректно отрабатывать любые исключения, возникающие на уровне SQL-сервера.

← На главную