При работе с высоконагруженными базами данных на платформе 1С:Предприятие 7.7 программисты часто сталкиваются с аппаратными и архитектурными ограничениями системы. Одной из самых неприятных проблем является внезапное завершение работы программы с заголовком Microsoft Visual C++ Runtime Library и сообщением Runtime Error!. Особенно часто это происходит при использовании внешней компоненты 1С++ для выполнения прямых запросов к SQL-серверу. Проанализируем причины этой ошибки и найдем эффективные способы её устранения.
Рассмотрим ситуацию, когда запрос по регистру (например, остатки и обороты по коробкам с высокой детализацией) прекрасно работает на старых данных, но вызывает крах системы при попытке сформировать отчет за текущий период. Проблема обычно кроется не в самом коде запроса, а в менеджменте оперативной памяти и структуре данных в SQL.
Проанализируем основные факторы, приводящие к Runtime Error:
1cv7s.exe является 32-битным и по умолчанию не может адресовать более 2 ГБ оперативной памяти. На практике вылеты начинаются гораздо раньше — при достижении 700–800 МБ, так как 1С требуется непрерывный блок памяти для размещения больших объектов, таких как ТаблицаЗначений.$Справочник.Продукт, компонента 1С++ создает внутренние объекты 1С для каждой строки результата. Если в выборке тысячи уникальных элементов, память «замусоривается» мелкими объектами, и система не может выделить место под новые данные..exe файлов или динамически загружаемых библиотек, таких как 1cpp.dll.Это самое эффективное решение, если проблема вызвана избыточным количеством записей в таблице итогов. Разберем по шагам, как это реализовать.
Если регистр содержит миллионы записей, которые в сумме дают ноль, но формально не закрыты, SQL-сервер продолжает их учитывать. Рассмотрим алгоритм «мягкой свертки» без изменения периода актуальности:
После проведения такого документа SQL-таблицы итогов физически уменьшатся, и запрос через ODBCRecordset начнет летать. Как показала практика, даже сброс остатков на начало текущего года позволяет отчету, который раньше вылетал, формироваться за считанные секунды.
Если данных объективно много и они все нужны в отчете, нам следует изменить подход к получению данных. Рассмотрим, как уменьшить нагрузку на оперативную память 1С.
Посмотрим на пример типичного запроса, который может вызвать проблему:
ТекстЗапроса = "
|SELECT
| $Рег.Продукт as [Продукт $Справочник.Продукты],
| $Рег.Партия as [Партия $Справочник.Партии],
| Рег.КоличествоКоробокОстаток as Кол
|FROM
| $РегистрОстатки.Коробки(:КонДата~,,
| (Продукт, Партия),
| (КоличествоКоробок)) as Рег";
RS.УстПараметр("КонДата", ВыбКонДата);
ТЗ = RS.ВыполнитьИнструкцию(ТекстЗапроса);
Чтобы избежать вылета, попробуем отказаться от типизации на уровне SQL-запроса, если строк очень много. Мы можем получить идентификаторы объектов как строки, а типизировать их уже в момент вывода или обработки. Это сэкономит память, затрачиваемую на создание объектов Internal ID.
Также проанализируем использование временных таблиц. Вместо того чтобы сразу выгружать всё в ТЗ, можно использовать конструкцию SELECT ... INTO #TempTable. Это позволит SQL-серверу обработать данные внутри себя, а 1С получит уже отфильтрованный и сгруппированный результат.
Если отчет упорно требует более 1 ГБ памяти, воспользуемся техническими средствами расширения адресного пространства. Рассмотрим вариант использования модифицированного 1cv7s.exe, в котором установлен флаг LARGE_ADDRESS_AWARE.
Важные условия для работы этого метода:
boot.ini прописать ключ /3GB, что крайне не рекомендуется для современных серверов.Если при запуске от имени администратора компонента 1cpp.dll не грузится с ошибкой Неудачная попытка создания объекта (ODBCRecordset), это означает проблему регистрации библиотеки в реестре Windows. Разберем, как это исправить:
regsvr32 "C:\ПутьКБазе\1cpp.dll".BIN).Чтобы минимизировать риск Runtime Error, придерживайтесь следующих правил при разработке на 1С 7.7 + 1С++:
TOP в запросах при отладке, чтобы понять, на каком объеме данных происходит падение.ВыполнитьИнструкцию(), которая сразу грузит всё в ТЗ, рассмотрите возможность использования Открыть() и обхода результата методом Вперёд(). Это позволит обрабатывать строки по одной, не занимая память под всю таблицу целиком.$Справочник только для тех полей, которые действительно нужны как объекты 1С. Для простых артикулов или номеров коробок достаточно строкового представления.Проанализировав все указанные способы, можно сделать вывод: в большинстве случаев Runtime Error в 1С 7.7 — это сигнал о том, что данные в базе стали слишком «рыхлыми», а системные ресурсы исчерпаны. Сочетание очистки итогов регистра и грамотной настройки прав доступа к компонентам позволяет полностью решить эту проблему.