Как обойти ограничение в 2 ГБ на размер временного файла при выполнении запроса в 1С 7.7?

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

При работе с большими объемами данных в устаревших, но все еще актуальных системах на базе 1С:Предприятие 7.7, разработчики часто сталкиваются с критической ошибкой CODEBASE ERROR 120 error writing to file. Эта ошибка обычно сопровождается аварийным завершением работы программы. Проанализируем ситуацию: в момент выполнения сложного отчета или обработки данных временный файл в папке Temp (обычно с расширением .dbf) достигает размера ровно 2 ГБ, после чего система «вылетает».

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

Выясним причину: почему возникает предел в 2 ГБ?

Разберем техническую составляющую. Платформа 1С 7.7 использует для работы с базами данных движок CodeBase. В этом движке для адресации смещений внутри файлов используются 32-битные знаковые целые числа (signed 32-bit integer). Максимальное значение, которое может принять такое число, составляет 2 147 483 647 байт, что и соответствует 2 гигабайтам.

Даже если ваша операционная система Windows 10/11 и файловая система NTFS позволяют создавать файлы размером в терабайты, сама программа 1С 7.7 просто «не умеет» обращаться к данным, которые находятся в файле дальше отметки в 2 ГБ. Как только временная таблица, формируемая запросом, перешагивает этот порог, драйвер CodeBase выдает ошибку записи.

Важное замечание по SQL-версии: многие полагают, что использование MS SQL Server полностью решает проблему. Однако это не так для «черных» (стандартных) запросов. Рассмотрим механизм: при выполнении стандартного объекта Запрос, 1С 7.7 часто выкачивает промежуточные данные из SQL-таблиц во временные локальные DBF-файлы на клиентской машине для выполнения группировок и расчета итогов средствами движка 1С. Таким образом, даже на SQL-версии вы можете получить CODEBASE ERROR 120, если выборка слишком велика.

Решение 1: Использование прямых запросов через компоненту 1С++

Это самый прогрессивный и эффективный метод. Прямые запросы позволяют полностью исключить использование промежуточных DBF-файлов и заставить SQL-сервер выполнять всю тяжелую работу на своей стороне.

Разберем, как это работает. При использовании внешней компоненты 1C++ (библиотека 1cpp.dll), мы отправляем инструкции на языке T-SQL непосредственно к СУБД. Результат возвращается в 1С уже в виде объекта ТаблицаЗначений или ИндексированнаяТаблица. Поскольку данные передаются в оперативную память процесса 1С, ограничение файлового движка CodeBase на них не распространяется.

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


// Создание объекта для выполнения прямого запроса
ОДБК = СоздатьОбъект("ODBCRecordset");
ТекстЗапроса = "
|SELECT 
|    Жур.IDDOC as [Документ $Документ],
|    Жур.IDDOCDEF as Документ_вид,
|    Спр.ID as [Товар $Справочник.Номенклатура],
|    Сум(Рег.Sum) as Сумма
|FROM 
|    $Регистр.Продажи as Рег
|INNER JOIN 
|    _1SJOURN as Жур ON Рег.IDDOC = Жур.IDDOC
|INNER JOIN 
|    $Справочник.Номенклатура as Спр ON Рег.Товар = Спр.ID
|WHERE 
|    Жур.DATE_TIME_IDDOC BETWEEN :НачДата AND :КонДата~
|GROUP BY 
|    Жур.IDDOC, Жур.IDDOCDEF, Спр.ID
|";
ОДБК.УстановитьТекстовыйПараметр("НачДата", ВыбНачПериода);
ОДБК.УстановитьТекстовыйПараметр("КонДата", ВыбКонПериода);
ТЗ = ОДБК.ВыполнитьИнструкцию(ТекстЗапроса);

В данном случае объем данных ограничен только оперативной памятью (около 2-3 ГБ для 32-битного приложения), но, как правило, результат выборки значительно компактнее промежуточных данных «черного» запроса.

Решение 2: Дробление выполнения запроса по периодам или объектам

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

Рассмотрим алгоритм действий:

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

Пример программного кода для реализации этого подхода:


ТЗ_Общая = СоздатьОбъект("ТаблицаЗначений");
ТЗ_Общая.НоваяКолонка("Товар");
ТЗ_Общая.НоваяКолонка("Количество");

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

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

Иногда объем временного файла можно существенно сократить, пересмотрев саму структуру запроса. Проанализируем типичные ошибки, увеличивающие размер Temp-файлов:

Решение 4: Использование компоненты 1SQLite

Еще один продвинутый метод — использование библиотеки 1SQLite.dll. Она позволяет создать в памяти или во временном файле базу данных формата SQLite. В отличие от штатного DBF, SQLite не имеет жесткого ограничения в 2 ГБ (точнее, его лимиты достигают терабайтов).

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

Резюме и рекомендации

Подведем итоги нашего исследования. Если вы столкнулись с ошибкой CODEBASE ERROR 120 при достижении файлом 2 ГБ, у вас есть три основных пути:

  1. Для SQL-версии: Однозначно переходите на прямые запросы через 1С++. Это снимет ограничения и ускорит формирование отчетов в 10-100 раз.
  2. Для файловой версии: Используйте 1SQLite для обработки больших массивов данных или дробите запросы на мелкие периоды.
  3. Общая гигиена: Проверьте переменные окружения TEMP и TMP в Windows. Убедитесь, что они указывают на диск с достаточным свободным местом, хотя это и не спасет от лимита в 2 ГБ, но предотвратит другие ошибки записи.

Помните, что ограничение в 2 ГБ — это архитектурная особенность платформы 1С 7.7, и «вылечить» её системными настройками Windows невозможно. Только изменение способа выборки данных позволит вам работать с по-настоящему большими базами.

← На главную