Недостаточно памяти с использованием Postgres в Java

Итак, у нас есть веб-приложение, работающее через JBoss, и у нас возникает ошибка OutOfMemory при попытке вставить много строк в несколько таблиц базы данных postgres. Это полная среда для этой ошибки:
* JBoss 4.3.x GA
* Java 1.6.0
* Гибернация 3.0
* postgreSQL-8.3 (драйвер)
О фактической кодовой рабочей среде:
* Сложность в том, что мы анализируем огромное количество XML-документов, каждый из которых загружается отдельно с определенного URL-адреса (1 URL = 1 XML). Мы достигаем этого, имея EJB, который распределяет сгенерированные URL-адреса в очередь, а затем пул MDB подключается с использованием потоков и генерирует документы (обратите внимание, что нам действительно пришлось увеличить память стека из-за размера XML-документов, и мы застрял с необходимостью получить весь документ в одном потоке), как только документ сгенерирован, он переходит в другую очередь, где его прослушивает другой пул MDB. Эти MDB анализируют документ, сохраняя информацию в нескольких объектах (по крайней мере, 5), которые затем сохраняются в DB (обратите внимание, что управление транзакциями установлено на "ФАСОЛЬ" и запускается и фиксируется во время каждой работы MDB). Последовательная обработка URL-адресов не является вариантом из-за количества обрабатываемых URL-адресов, это займет около 2 месяцев ... lol

Проблема в том ... что мы анализируем и сохраняем около 200 URL-адресов и начинаем получать ошибку нехватки памяти для postgreSQL. Любые идеи??

Заранее спасибо!!

ТАКЖЕ: может быть полезно знать, что эта ошибка не возникала раньше (я проанализировал несколько тысяч этого XML), только создание документов и анализ некоторых из них на некоторые объекты, похоже, не доставляли проблем. Проблемы начались, когда мы начали разбирать все больше и больше документа на соответствующие ему сущности. (Как одна сущность, имеющая список «функций» [другая сущность проанализирована из того же XML])

Когда вы говорите «не хватает памяти для postgreSQL», вы имеете в виду, что ваш экземпляр jboss выдает исключение, или вы имеете в виду, что самому демону PostgreSQL не хватает памяти?

Paul Tomblin 17.12.2008 16:23

Исключение показано в Java Stack Trace, но я думаю, что оно создается на стороне PostgreSQL.

Juan Manuel 17.12.2008 16:33

Вы видите что-нибудь в файлах журнала PostgreSQL Daemon? По крайней мере, опубликуйте трассировку стека, которую вы видите.

Paul Tomblin 17.12.2008 16:38

Фактически, это первая строка трассировки стека: 11: 36: 17,730 WARN [PersistenceManager] SQLException перехвачено - предполагая, что обнаружена взаимоблокировка, попробуйте: 4 java.sql.SQLException: out of memory

Juan Manuel 17.12.2008 16:39

И журнал PostgreSQL на сервере не показывает никаких отклонений, но я читал, что драйвер PostgreSQL сохраняет курсоры как на стороне сервера, так и на стороне клиента ... Я не уверен.

Juan Manuel 17.12.2008 16:40

Можете ли вы сказать нам, какой у вас установлен максимальный размер кучи (я предполагаю, это то, что вы имели в виду, когда сказали, что вам нужно «увеличить память стека»), а также какие у вас есть конфигурации для подключения / пула БД?

matt b 17.12.2008 17:40

Нет ... Мне пришлось увеличить стековую память, потому что генерация документа dom выполняется в стеке, поэтому мне пришлось изменить исходную конфигурацию для JVM в JBoss и все понял. Фактически, это мои настройки памяти для JVM в JBoss: <i> -Xms256m -Xmx512m -Xss4m -XX: MaxPermSize = 256m </i>

Juan Manuel 17.12.2008 17:48

Что касается конфигурации БД, пулом подключений управляет сервер приложений. У него не должно быть проблем, пока сервер правильно управляет подключениями.

Juan Manuel 17.12.2008 17:52

Вот вероятная первопричина такой проблемы (и решение на низком уровне, ах!): benjchristensen.com/2008/05/27/…

jmount 01.12.2009 21:42
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
9
1 697
2

Ответы 2

Похоже, вы храните все компоненты для всех 200 документов в памяти.

Вместо того, чтобы постоянно хранить все данные в ОЗУ, постарайтесь как можно быстрее избавиться от них.

Поэтому, когда вы закончите чтение данных для некоторого bean-компонента, сохраните их, а затем забудьте об этом (установите ссылку на объект на null), за исключением, возможно, ключа, который вам нужен для создания ссылок.

Если вы не можете этого сделать, используйте профилировщик, чтобы убедиться, что вы не сохраняете ссылку на документ после его анализа. Обычно вам не нужно нигде хранить весь документ после его сохранения в БД. Если это проблема, создайте таблицу со ссылками, которая позволит вам связывать документы и просто хранить ключи в этой таблице в памяти (вместо всего документа).

Аарон: Я избавляюсь от любого компонента Entity или экземпляра документа, как только они мне больше не нужны, именно тогда я их сохраняю. Бен: Я использую два пула, чтобы сэкономить время, потому что получение документа из потока URL занимает секунду, а его анализ - как другой, поэтому я стараюсь «имитировать» параллельную обработку вместо того, чтобы выполнять загрузку и синтаксический анализ / сохраняются последовательно. Спасибо обоим!

Juan Manuel 17.12.2008 16:44

Короткий ответ: требуется дополнительная информация. Я предлагаю использовать такой инструмент, как JProfiler, чтобы понять, где потребляется память.

Основываясь на описанном вами дизайне: зачем использовать два бассейна? Если бы у вас был только пул для URL-адресов, рабочие потоки могли бы извлекать из этого пула, анализировать URL-адрес и создавать объектные компоненты, сохраняя их в БД.

Непонятно, зачем вам нужен промежуточный шаг XML, который звучит как вероятный источник большого потребления памяти.

Другие вопросы по теме