Как устранить ошибку «Время ожидания истекло» при программном создании документов в 1С 7.7 на SQL?

Программист 1С v7.7 Торговля и дистрибуция
← На главную

При работе с многопользовательскими базами данных 1С:Предприятие 7.7 в SQL-варианте разработчики часто сталкиваются с ситуацией, когда программное создание документов (например, автоматическая генерация ПКО на основании Товарного чека) прерывается ошибкой «Время ожидания истекло». Это происходит из-за специфики механизмов блокировок платформы 7.7. В данной статье мы детально разберем, почему возникают такие задержки, как правильно настроить систему и какой программный код поможет гарантированно создать документ даже в условиях высокой нагрузки на базу.

Разберем причину возникновения блокировок

Для начала проанализируем ситуацию с технической точки зрения. В отличие от современных версий платформы, 1С 7.7 использует пессимистическую модель блокировок. Когда любой пользователь или процесс пытается создать новый документ методом Новый() или записать существующий методом Записать(), система накладывает блокировку на общие таблицы базы данных. Самая «популярная» из них — _1SJOURN (общий журнал документов). Если в этот же момент другой пользователь проводит тяжелый документ или формирует сложный отчет, SQL-сервер блокирует таблицу целиком, и ваш процесс встает в очередь.

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

Решение 1: Программное создание документа в цикле «Попытка — Исключение»

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

Проанализируем пример кода, предложенный участниками сообщества:


// Определим количество попыток создания документа
КоличествоПопыток = 100; 
ДокСоздан = 0;

Пока КоличествоПопыток > 0 Цикл
    Попытка 
        НовыйДок.Новый(); // Пытаемся инициализировать новый документ
        ДокСоздан = 1;
        Прервать; // Если успешно — выходим из цикла
    Исключение
        // Если база занята, управление передается сюда
        КоличествоПопыток = КоличествоПопыток - 1;
        // Здесь можно добавить небольшую паузу
    КонецПопытки; 
КонецЦикла;

Если ДокСоздан = 0 Тогда
    Предупреждение("Не удалось создать документ из-за блокировок таблиц базы данных.");
КонецЕсли;

Важно понимать, что аналогичный подход следует применять и при вызове метода Записать() или Провести(). Именно на этапе записи в SQL-таблицы происходит основной захват ресурсов.

Решение 2: Настройка времени ожидания захвата таблиц

Для того чтобы цикл, описанный выше, работал эффективно, необходимо изменить системную настройку «Время ожидания захвата таблиц». Выясним, почему это критично. Если в настройках стоит 30 секунд, то каждая неудачная итерация цикла в блоке Исключение будет длиться полминуты. При 100 попытках программа зависнет на вечность.

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

Где найти эту настройку:

  1. Запустите 1С:Предприятие в режиме пользователя.
  2. Перейдите в меню Сервис — Параметры.
  3. Откройте закладку Общие.
  4. Найдите поле «Время ожидания захвата таблиц базы данных» и установите значение 0.

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

Решение 3: Оптимизация работы с транзакциями

Проанализируем влияние транзакций. Использование конструкции НачатьТранзакцию() — ЗафиксироватьТранзакцию() часто является причиной усиления блокировок. Если вы открываете транзакцию, а затем внутри нее запускаете длительный цикл создания или заполнения документов, вы сами становитесь источником проблем для остальных пользователей, удерживая таблицы базы данных.

Выясним правильную стратегию работы:

Дополнительные рекомендации и использование пауз

Иногда бесконечный цикл без пауз может избыточно нагружать процессор сервера. Чтобы этого избежать, рассмотрим возможность добавления микро-паузы. Поскольку штатной команды Sleep в 1С 7.7 нет, можно воспользоваться внешними компонентами (например, FormEx или 1С++) или системными вызовами.

Посмотрим, как можно реализовать проверку на запись более изящно:


Док = СоздатьОбъект("Документ.ПриходныйКассовый");
Успех = 0;
Для Итерация = 1 По 50 Цикл
    Попытка
        Док.Новый();
        Док.Записать(); // Предварительная запись для захвата номера
        Успех = 1;
        Прервать;
    Исключение
        // Небольшая задержка перед следующей попыткой
    КонецПопытки;
КонецЦикла;

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

Резюме для реализации

Подводя итог нашему разбору, выделим основные шаги для стабильного программного создания документов в SQL-версии 7.7:

  1. Всегда используйте цикл вокруг методов Новый(), Записать() и Провести().
  2. Установите таймаут захвата таблиц в 0. Это сделает реакцию системы на блокировку мгновенной, что критично для работы программных циклов.
  3. Минимизируйте транзакции. Не держите транзакцию открытой, пока пользователь что-то выбирает или пока выполняются длительные расчеты.
  4. Проверяйте результат. Обязательно анализируйте переменную-флаг (например, ДокСоздан) после завершения цикла, чтобы корректно сообщить пользователю о результате операции.

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

← На главную