При переносе данных между информационными базами 1С с помощью стандартной обработки «Универсальный обмен данными в формате XML» нередко возникает критическая ошибка «Недостаточно памяти» (Out of memory). Чаще всего это происходит на этапе обработки регистра сведений ПрисоединенныеФайлы или соответствующих справочников хранения файлов.
Разберем причины возникновения этой ошибки и рассмотрим эффективные практические способы ее решения.
Проанализируем ключевые факторы, приводящие к исчерпанию оперативной памяти:
1cv8.exe, процессу доступно не более 2–3 ГБ виртуального адресного пространства. При формировании огромного массива данных память фрагментируется и быстро заканчивается.ДвоичныеДанные или ХранилищеЗначения) в формат XML применяется кодирование Base64. Оно не только увеличивает итоговый размер данных примерно на 33%, но и создает в оперативной памяти множество тяжелых строковых объектов.ПрисоединенныеФайлы в типовых конфигурациях является непериодическим и независимым. Задать для него отбор по стандартному периоду выгрузки в обработке обмена невозможно, поэтому платформа пытается выгрузить весь массив записей сразу.Рассмотрим наиболее гибкий подход, когда структура метаданных (справочники присоединенных файлов) уже перенесена стандартным обменом, но сами двоичные данные файлов отсутствуют. В этом случае мы можем напрямую подключиться из базы-приемника к базе-источнику и загрузить содержимое файлов порциями с помощью методов подсистемы «Работа с файлами» Библиотеки стандартных подсистем (БСП).
Разберем пошаговый пример кода для обновления данных файлов в базе-приемнике:
// Подключаемся к базе-источнику через COM-соединение
ПараметрыПодключения = "Srvr=""ServerName"";Ref=""SourceBase"";Usr=""Admin"";Pwd=""Password"";";
COMСоединитель = Новый COMОбъект("V83.COMConnector");
ДругаяБаза = COMСоединитель.Connect(ПараметрыПодключения);
// Получаем ссылку на файл в базе-источнике и ссылку в текущей базе
// Передаем двоичные данные через Base64-строку и временное хранилище
ДвоичныеДанныеФайла = Base64Значение(ДругаяБаза.Base64Строка(ДругаяБаза.ПрисоединенныеФайлы.ПолучитьДвоичныеДанныеФайла(СсылкаНаСправочникВДругойБазе)));
ПараметрыФайла = Новый Структура;
ПараметрыФайла.Вставить("АдресФайлаВоВременномХранилище", ПоместитьВоВременноеХранилище(ДвоичныеДанныеФайла, Новый УникальныйИдентификатор));
ПараметрыФайла.Вставить("АдресВременногоХранилищаТекста", Новый УникальныйИдентификатор);
// Обновляем тело файла в текущей информационной базе через штатный метод БСП
ПрисоединенныеФайлы.ОбновитьПрисоединенныйФайл(СсылкаНаСправочникВЭтойБазе, ПараметрыФайла);
Если же файлы переносятся с нуля (вместе с созданием элементов справочника), в целевой базе используется процедура ПрисоединенныеФайлы.ДобавитьПрисоединенныйФайл.
При реализации пакетной обработки обязательно очищайте переменные на каждой итерации цикла (присваивая им значение Неопределено) и периодически фиксируйте транзакции, чтобы оперативная память вовремя освобождалась сборщиком мусора.
Рассмотрим штатный и наиболее надежный способ работы с большими объемами вложенных файлов:
Если необходимо использовать стандартную выгрузку через XML без изменения архитектуры хранения файлов, запустим обработку в 64-разрядной версии толстого или тонкого клиента (1cv8.exe x86-64). Это полностью снимает ограничение адресного пространства в 2–3 ГБ, позволяя платформе задействовать весь объем физической памяти сервера или рабочей станции.
В настройках обработки «Универсальный обмен данными в формате XML» включим режим выгрузки объектами частями. Установка фиксированного лимита объектов в порции (например, по 500–1000 объектов) заставляет платформу сбрасывать порции данных на диск и своевременно очищать буфер оперативной памяти.