При эксплуатации связки 1С:Предприятие и PostgreSQL системные администраторы часто сталкиваются с ошибкой «out of memory for query result». Эта проблема особенно актуальна при построении тяжелых отчетов или выполнении объемных обменов данными. Проанализируем природу этой ошибки, выясним, почему она возникает даже при наличии свободной оперативной памяти на сервере, и разберем по шагам методы её решения.
Первое, что нам необходимо понять: несмотря на то, что ошибка упоминает СУБД, она генерируется не ядром PostgreSQL, а клиентской библиотекой libpq. Эту библиотеку сервер приложений 1С (процесс rphost) использует для взаимодействия с базой данных. Разберем механизм взаимодействия подробнее:
libpq на стороне сервера 1С пытается выделить в адресном пространстве процесса rphost непрерывный буфер памяти, чтобы принять весь объем данных от СУБД целиком.rphost не может выделить такой объем памяти (из-за общего лимита или фрагментации), библиотека выдает ошибку «out of memory for query result».Таким образом, это не серверная ошибка PostgreSQL, а ограничение на стороне клиента (в данном случае — сервера приложений 1С), которому не хватает адресного пространства для получения ответа.
Проанализируем ситуацию, описанную в теме: используется 32-битный сервер 1С на 64-битной операционной системе Windows Server. Рассмотрим технические ограничения такой конфигурации:
Large Address Aware, который в современных версиях 1С включен по умолчанию) и запуске на 64-битной ОС, лимит расширяется до 3.5–4 ГБ.rphost, достигая отметки в 3–3.5 ГБ, становится крайне нестабильным. Он не может выделить крупный кусок памяти под результат запроса, даже если суммарно свободная память в системе исчисляется десятками гигабайт.Выясним, почему помогает перезагрузка служб. В процессе долгой работы память rphost подвергается фрагментации. Она становится похожа на «швейцарский сыр»: много мелких свободных участков, но ни одного цельного куска размером, скажем, в 500 МБ. После перезапуска память чиста, фрагментация нулевая, и тот же самый тяжелый отчет временно начинает проходить без ошибок.
Рассмотрим последовательность действий для окончательного устранения ошибки, начиная с самых эффективных.
Это стратегически верное и единственное надежное решение. 64-битный процесс rphost практически не ограничен в объеме используемой оперативной памяти (лимит измеряется терабайтами). Это позволяет выделять любые необходимые буферы под результаты запросов. Если ваша лицензия позволяет использовать 64-битную версию сервера, выполните переход в первую очередь.
Проанализируем настройки конфигурационного файла postgresql.conf. Неправильные значения могут провоцировать СУБД отдавать слишком избыточные объемы данных, которые «топят» клиентский процесс.
Обратим внимание на параметр work_mem. В исходном сообщении он был установлен в 256MB. Рассмотрим, почему это может быть опасно:
work_mem определяет объем памяти для одной операции сортировки или группировки внутри запроса.256MB * 10 = 2.5GB оперативной памяти только на выполнение.work_mem заставляет СУБД формировать огромные наборы данных в памяти, которые затем отправляются в 32-битный rphost, вызывая его падение.Для систем на базе 1С рекомендуем устанавливать более умеренные значения work_mem (например, от 32MB до 64MB), чтобы при очень тяжелых запросах СУБД чаще использовала временные файлы на диске, не перегружая оперативную память клиента.
Также проверьте параметр cursor_tuple_fraction. Установка значения 1.0 может помочь оптимизировать планировщик на получение всего объема данных, что иногда положительно сказывается на стабильности передачи больших наборов строк.
Если переход на 64-битную версию временно невозможен, проанализируем настройки кластера 1С. Разберем возможность разделения нагрузки:
rphost. Если один пользователь запустит «тяжелый» отчет и вызовет ошибку в своем процессе, это не затронет остальных и даст каждому процессу свой отдельный лимит в 3.5 ГБ.Чтобы понять, какой именно отчет или обработка вызывают ошибку, настроим Технологический журнал (ТЖ). Нам нужно отловить событие DBPOSTGRS. Создадим файл logcfg.xml следующего содержания:
<config xmlns="http://v8.1c.ru/7.4/puls/logcfg">
<log location="C:\LOGS\POSTGRES" history="24">
<event>
<eq property="Name" value="DBPOSTGRS"/>
<not>
<eq property="Context" value=""/>
</not>
</event>
<property name="All"/>
</log>
</config>
Анализируя логи, мы сможем увидеть текст SQL-запроса, непосредственно предшествующего ошибке. Часто выясняется, что проблема в некорректно написанном запросе (например, соединение таблиц без условий, приводящее к декартову произведению), который пытается выгрузить миллионы строк. Оптимизация такого запроса на уровне конфигурации 1С может решить проблему без апгрейда железа.
Версия PostgreSQL 9.4, упомянутая в обсуждении, является устаревшей. Рекомендуем рассмотреть переход на актуальные версии (12, 13 или выше), адаптированные для 1С (например, от Postgres Professional). В новых версиях значительно улучшена работа с памятью и оптимизированы механизмы очистки временных таблиц, что снижает вероятность возникновения ошибок переполнения буфера.
Подведем итог нашему анализу. Ошибка «out of memory for query result» — это классический признак «упирания» в потолок 32-битной архитектуры.
Для быстрого решения:
rphost в консоли кластера.Для окончательного решения:
Помните, что настройка параметров shared_buffers или effective_cache_size влияет на производительность поиска данных, но почти не помогает при ошибке out of memory на стороне клиента, так как корень проблемы лежит в этапе передачи уже сформированного результата запроса в адресное пространство 1С.