Почему 1С 7.7 SQL зависает при загрузке обмена XML и выдает ошибку Timeout expired?

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

При выполнении обмена данными между современными конфигурациями (например, 1С:Управление торговлей 11) и базами на платформе 1С:Предприятие 7.7 под управлением MS SQL Server нередко возникает ситуация, когда процесс загрузки внезапно останавливается. В окне состояния отображается обработка определенного числа объектов, процесс загружает процессор, а у активных пользователей в этот момент появляются критические ошибки вида SQL State: HYT00 Native: 0 Message: [Microsoft][ODBC SQL Server Driver]Timeout expired. При этом запись и проведение документов блокируются по всей базе.

Разберем детально, почему возникает подобное поведение платформы, как локализовать узкое место и как правильно настроить поиск и запись объектов при пакетном обмене данными.

Анализ механизма поиска и причины блокировки базы

Выясним причину, которая чаще всего приводит к «мертвому» зависанию базы при выполнении выгрузки или загрузки. Основная проблема кроется в алгоритмах сопоставления загружаемых объектов с существующими документами в базе 1С 7.7.

Рассмотрим, как работает поиск в 1С 7.7 на уровне СУБД:

  1. Если в правилах обмена или обработке загрузки поиск документа выполняется по стандартным реквизитам (Дата и НомерДок), платформа использует штатные индексы системной таблицы журнала документов _1SJOURN. Такой поиск выполняется практически мгновенно методом точечной выборки по индексу.
  2. Если же сопоставление перенастроено на пользовательские реквизиты (например, ДатаСоздания, НомерСоздания или строковый идентификатор) без включения отбора, стандартный метод НайтиПоРеквизиту() не может использовать индекс.
  3. В случае отсутствия явного поиска по индексу платформа 1С 7.7 инициирует обратную выборку документов от текущей даты вглубь истории базы данных в попытке найти совпадение по значениям.
  4. Если загружаемый документ является абсолютно новым и в базе отсутствует, платформа выполняет полный перебор (Table Scan) всей таблицы журнала _1SJOURN и соответствующих таблиц шапок документов DH<ID> вплоть до самой первой записи в базе (например, за 10–12 лет работы).

При объеме базы в сотни тысяч или миллионы документов такое сканирование накладывает разделяемые блокировки (Shared Locks) на диапазоны строк. При интенсивном параллельном чтении происходит эскалация блокировок до уровня всей таблицы, из-за чего все остальные пользователи при попытке выполнить методы Записать() или Провести() получают ошибку таймаута ожидания блокировки Timeout expired.

Оптимизация идентификации документов в правилах обмена

Чтобы исключить сканирование всей таблицы журнала при загрузке новых документов, необходимо правильно организовать структуру реквизитов и процедуру поиска в конфигураторе 1С 7.7.

Разберем по шагам правильную настройку:

  1. Откроем конфигуратор 1С 7.7 и перейдем к структуре метаданных нужного документа.
  2. В свойствах реквизита, по которому планируется производить сопоставление (например, ИД_Обмена или НомерСоздания), обязательно установим флаг «Отбор по реквизиту» (или «Сортировка»). Это заставит СУБД создать отдельный индекс по полю соответствующей таблицы.
  3. В коде загрузки исключим циклы обратного перебора документов без ограничения диапазона дат. Поиск должен выполняться строго индексным методом:

Док = СоздатьОбъект("Документ.РасходнаяНакладная");
Если Док.НайтиПоРеквизиту("ИД_Обмена", ЗначениеИдентификатора, 1) = 1 Тогда
    // Документ найден по индексу, обновляем реквизиты
    Док.Записать();
Иначе
    // Документ не найден, создаем новый объект без сканирования истории
    Док.Новый();
    Док.ИД_Обмена = ЗначениеИдентификатора;
    Док.Записать();
КонецЕсли;

Управление транзакциями при массовой загрузке

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

Для предотвращения взаимных блокировок применим порционную фиксацию данных с механизмом повторных попыток при возникновении конфликтов:


КоличествоВТранзакции = 0;
НачатьТранзакцию();

Пока ЧтениеXML.Прочитать() Цикл
    // Код чтения и заполнения объекта
    Попытка
        ОбъектДокумент.Записать();
        Если ФлагПроведения = 1 Тогда
            ОбъектДокумент.Провести();
        КонецЕсли;
    Исключение
        ОтменитьТранзакцию();
        ЗаписьЖурналаРегистрации("Ошибка записи документа: " + ОписаниеОшибки(), 
                                 "ОбменXML", "Загрузка", 3);
        // Запуск следующей транзакции для продолжения обработки
        НачатьТранзакцию();
        КоличествоВТранзакции = 0;
        Продолжить;
    КонецПопытки;
    
    КоличествоВТранзакции = КоличествоВТранзакции + 1;
    
    // Фиксируем данные порциями по 50 документов
    Если КоличествоВТранзакции >= 50 Тогда
        ЗафиксироватьТранзакцию();
        НачатьТранзакцию();
        КоличествоВТранзакции = 0;
    КонецЕсли;
КонецЦикла;

Если КоличествоВТранзакции > 0 Тогда
    ЗафиксироватьТранзакцию();
КонецЕсли;

Регламентные операции и настройки MS SQL Server

Если оптимизация кода выполнена, но СУБД продолжает выбирать неоптимальные планы выполнения запросов (например, сканирование кластерного индекса вместо поиска по некластерному индексу), необходимо проверить состояние базы на стороне SQL Server.

  1. Обновление статистики: На устаревшей статистике оптимизатор SQL Server может ошибочно оценивать селективность условий и сканировать таблицы целиком. Необходимо выполнить обновление статистики для таблиц _1SJOURN, таблиц шапок документов DH* и таблиц проводок/регистров.
  2. Ограничения редакции MS SQL Express: Следует помнить, что редакции SQL Server Express имеют жесткое ограничение на максимальный размер базы данных (10 ГБ для версий 2008 R2 и выше). Это ограничение учитывает только размер файлов данных (MDF/NDF), журнал транзакций (LDF) в лимит не входит. При приближении к лимиту (например, 9.5 ГБ) необходимо запланировать свертку базы данных или переход на стандартную редакцию СУБД.
  3. Модель восстановления (Recovery Model): Для баз данных с интенсивным обменом в среде Express рекомендуется использовать простую модель восстановления (Simple), чтобы файл журнала транзакций не разрастался бесконтрольно и не создавал дополнительную нагрузку на дисковую подсистему.
← На главную