Как исправить ошибку СУБД "Attempting to grow LOB beyond maximum allowed size" и ошибку разбора XML "Extra content at the end of the document" в 1С

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

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

Первая ошибка возникает на уровне СУБД Microsoft SQL Server: "Attempting to grow LOB beyond maximum allowed size of 2147483647 bytes" (Код ошибки SQL Server: 7119). Вторая ошибка возвращается встроенным XML-парсером платформы 1С: "Extra content at the end of the document" (Фатальная ошибка, позиция [1,1]). Мы подробно проанализируем физические причины возникновения этих сбоев и выработаем надежные архитектурные решения для их устранения.

Часть 1. Разбор ошибки СУБД: Attempting to grow LOB (Код 7119)

Для начала давайте разберемся, что представляет собой аббревиатура LOB в контексте СУБД MS SQL Server. Под LOB (Large Object) понимаются специализированные типы данных большого объема, такие как NVARCHAR(MAX), VARCHAR(MAX), VARBINARY(MAX), а также устаревшие типы TEXT, NTEXT и IMAGE. На уровне движка базы данных для хранения таких объектов выделяются отдельные страницы памяти вне основной таблицы.

СУБД Microsoft SQL Server накладывает жесткое физическое ограничение на максимальный размер любого одиночного значения этих типов — он не может превышать $2^{31} - 1$ байт, что составляет ровно 2 147 483 647 байт (2 ГБ). Если СУБД в процессе выполнения транзакции пытается записать в одну ячейку таблицы, передать в качестве одного параметра или обработать во временной таблице tempdb непрерывный массив данных, превышающий этот лимит, она аварийно завершает операцию с ошибкой 7119.

Выясним, почему это происходит при загрузке XML в 1С, ведь исходный размер файла на диске может быть существенно меньше 2 ГБ (например, около 1 ГБ):

  1. Накладные расходы кодирования Base64: Если выгружаемый XML-файл содержит двоичные данные (картинки, файлы PDF, скан-копии документов или архивы), они сериализуются по стандарту Base64. Специфика этого кодирования такова, что каждые 3 байта исходных бинарных данных преобразуются в 4 текстовых символа. Это приводит к гарантированному увеличению объема двоичных данных на 33%. Таким образом, исходный файл объемом 1.5 ГБ после сериализации превратится почти в 2 ГБ текста.
  2. Обработка данных в рамках одной транзакции: По умолчанию многие типовые механизмы обмена (включая обработку УниверсальныйОбменДаннымиXML) пытаются прочитать тяжелый файл обмена и зафиксировать все изменения в СУБД в рамках одной транзакции. При этом сервер 1С формирует огромные SQL-запросы, которые переполняют буфер транзакций и временные таблицы СУБД.
  3. Попытка записи объекта целиком в ХранилищеЗначения: Если логика вашей конфигурации предусматривает сохранение всего входящего XML-пакета во временное хранилище или специальный справочник (например, для истории обменов) в поле типа "Хранилище значения" (которое на уровне SQL транслируется в LOB-поле), то при превышении порога в 2 ГБ запись гарантированно завершится аварийно.

Решения для устранения ошибки SQL LOB 7119

Рассмотрим основные архитектурные подходы, которые позволят нам обойти ограничение СУБД в 2 ГБ.

Способ 1. Исключение двоичных данных из XML-структуры. Передача "тяжелых" бинарных файлов (картинки, документы) непосредственно внутри тела XML-документа является грубой архитектурной ошибкой. Вместо этого мы должны сохранять двоичные данные во внешнем хранилище (например, в сетевой папке, на FTP-сервере или в облачном объектном S3-хранилище). В самом XML-файле мы передаем только метаданные и относительную ссылку или уникальный идентификатор файла. При загрузке на стороне приемника сервер 1С должен программно скачивать файлы по ссылкам поочередно, исключая перегрузку памяти.

Способ 2. Пакетная выгрузка данных (Chunking). Если XML-файл разрастается до огромных размеров из-за колоссального количества выгружаемых документов или справочников, его необходимо дробить на пакеты еще на этапе генерации в источнике. Оптимальный размер одного пакета составляет от 50 до 100 МБ. Это гарантирует стабильную обработку файлов без критической нагрузки на оперативную память сервера приложений 1С и СУБД.

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

Часть 2. Разбор ошибки разбора XML: Extra content at the end of the document (Ошибка [1,1])

Теперь проанализируем вторую проблему, когда при загрузке файла через фоновое задание мы внезапно получаем фатальную ошибку разбора XML: "Extra content at the end of the document. Line 1, Position 1". Интересно, что при попытке открыть этот же файл в текстовом редакторе или браузере он выглядит абсолютно корректным, а при загрузке вручную на клиенте через интерактивную форму все отрабатывает без сбоев.

Разберем детально физические причины этого парадокса:

  1. Проблема сигнатуры BOM (Byte Order Mark) в UTF-8: BOM представляет собой специальную последовательность байтов (для UTF-8 это EF BB BF) в самом начале текстового файла, предназначенную для определения порядка байтов в потоке.
    • На клиенте: При запуске интерактивной обработки под управлением ОС Windows платформа 1С использует системные библиотеки Microsoft (такие как MSXML или механизмы Internet Explorer). Эти компоненты давно оптимизированы разработчиками Microsoft и умеют "на лету" корректно распознавать и отсекать BOM-символы перед передачей потока парсеру.
    • На сервере: Серверный процесс 1С rphost (особенно если сервер функционирует под ОС Linux или запущен под системной учетной записью usr1cv8 с нестандартными региональными настройками) задействует кроссплатформенный парсер (на базе библиотеки libxml2). Если локаль сервера настроена некорректно, парсер может воспринять BOM-байты как недопустимые символы (мусор) прямо перед объявлением XML-документа <?xml...>, либо неверно рассчитать длину считываемого потока. Это приводит к немедленному сбою с вердиктом "Extra content...".
  2. Проблемы сетевого кэширования файловой системы (SMB/CIFS): Обратите внимание на важный эксперимент, упомянутый в обсуждении темы: если просто переименовать файл на сетевом диске \\srv-s1cm1\ERP_SYNC\..., то ошибка разбора исчезает! Это классический признак кэширования сетевых папок ОС Windows. При циклической перезаписи файла обмена с фиксированным именем сетевые механизмы кэширования могут отдавать серверному процессу 1С устаревшую, частично заблокированную или недописанную версию файла. В результате парсер считывает поврежденный поток данных, доходит до непредвиденного конца файла или натыкается на блокировки чтения и выдает фатальную ошибку структуры.

Решения для устранения ошибки "Extra content" и проблем с BOM

Для предотвращения подобных ошибок при проектировании обменов на сервере необходимо строго следовать двум правилам.

Правило 1. Запись XML-файлов строго без BOM. При формировании файлов обмена в системе-источнике мы должны принудительно отключать запись сигнатуры BOM. В платформе 1С это реализуется с помощью правильной инициализации объекта ЗаписьТекста, где пятый параметр конструктора отвечает за вывод BOM-символов.

Проанализируем пример кода, гарантирующий создание файла UTF-8 без BOM:


// Правильная выгрузка XML без использования BOM
ПутьКФайлу = "\\srv-s1cm1\ERP_SYNC\UPP_ERPPM\MessageUPP_ERP.xml";

// Пятый параметр "Ложь" отключает запись BOM-символов
ТекстовыйФайл = Новый ЗаписьТекста(ПутьКФайлу, КодировкаТекста.UTF8, , , Ложь);

ЗаписьXMLДанных = Новый ЗаписьXML();
ЗаписьXMLДанных.ОткрытьФайл(ТекстовыйФайл);

// Производим запись структуры XML документа...
ЗаписьXMLДанных.ЗаписатьОбъявлениеXML();
// ... логика выгрузки объектов ...

ЗаписьXMLДанных.Закрыть();
ТекстовыйФайл.Закрыть();

Правило 2. Локальное чтение файлов на сервере 1С. Крайне не рекомендуется осуществлять чтение "тяжелых" XML-файлов напрямую по сетевым путям (таким как \\server\folder\file.xml) в методах серверного разбора. Сетевые задержки, микросбои сетевых адаптеров и механизмы блокировок файлов в многопоточной среде гарантированно будут приводить к сбоям парсинга.

Правильный алгоритм работы с сетевыми ресурсами на сервере должен выглядеть так:

  1. Программа формирует уникальное временное имя файла (например, с использованием UUID или временной метки), чтобы исключить конфликты кэширования сетевых имен.
  2. Копирует сетевой файл на локальный диск сервера приложений 1С во временный каталог (используя встроенный метод КопироватьФайл()).
  3. Производит локальное чтение и разбор скопированного файла.
  4. После успешного или аварийного завершения операции удаляет временный локальный файл.

Давайте посмотрим на реализацию этого отказоустойчивого алгоритма загрузки:


&НаСервере
Процедура ВыполнитьЧтениеФайлаОбменаНаСервере(Знач СетевойПутьКФайлу)
    
    // Генерируем уникальное имя для предотвращения кэширования SMB
    УникальныйИдентификаторФайла = Строка(Новый УникальныйИдентификатор);
    ЛокальныйПуть = КаталогВременныхФайлов() + УникальныйИдентификаторФайла + ".xml";
    
    // Копируем сетевой файл на локальный диск сервера 1С
    Попытка
        КопироватьФайл(СетевойПутьКФайлу, ЛокальныйПуть);
    Исключение
        ЗаписьЖурналаРегистрации("СинхронизацияДанных", УровеньЖурналаРегистрации.Ошибка,,,
            "Не удалось скопировать файл во временное хранилище сервера. Описание: " + ОписаниеОшибки());
        Возврат;
    КонецПопытки;
    
    ФайлОбмена = Новый ЧтениеXML();
    Попытка
        ФайлОбмена.ОткрытьФайл(ЛокальныйПуть);
        
        // Запускаем последовательное чтение файла
        Пока ФайлОбмена.Прочитать() Цикл
            // Здесь реализуется логика обработки узлов XML
            // Например, анализ элементов и запись в СУБД порциями
        КонецЦикла;
        
        ФайлОбмена.Закрыть();
        
    Исключение
        // Обязательно закрываем файл в случае ошибки, чтобы снять блокировку
        ФайлОбмена.Закрыть();
        
        // Удаляем временный файл перед генерацией исключения
        УдалитьФайлы(ЛокальныйПуть);
        
        ВызватьИсключение "Ошибка парсинга XML на сервере: " + ОписаниеОшибки();
    КонецПопытки;
    
    // Удаляем временную копию после успешной обработки
    Попытка
        УдалитьФайлы(ЛокальныйПуть);
    Исключение
        // Логируем ошибку удаления, но не прерываем работу
        ЗаписьЖурналаРегистрации("СинхронизацияДанных", УровеньЖурналаРегистрации.Предупреждение,,,
            "Не удалось удалить временный локальный файл: " + ОписаниеОшибки());
    КонецПопытки;
    
КонецПроцедуры

Применение данной методики позволяет полностью исключить влияние сетевых протоколов Windows/Samba на процесс парсинга данных, сводит к нулю вероятность возникновения ошибки "Extra content" из-за кэширования сетевых дескрипторов, а также изолирует разбор кодировки от специфических региональных настроек сетевых папок.

Подводя итог, мы видим, что успешная обработка больших объемов XML-данных в 1С требует комплексного подхода: оптимизации хранения двоичных файлов отдельно от текстового XML-пакета, отключения BOM-сигнатур при записи, порционного коммитирования транзакций в СУБД для обхода лимита LOB-объектов в 2 ГБ и обязательного локального кэшивания файлов на сервере приложений 1С для предотвращения сбоев сетевого ввода-вывода.

← На главную