2009-08-01 3 views
2

У меня есть приложение C++, которое использует PostgreSQL 8.3 для Windows. Мы используем интерфейс libpq.PostgreSQL, потребляющий большой объем памяти для постоянного соединения

У нас есть многопоточное приложение, в котором каждый поток открывает соединение и продолжает использовать его без PQFinish.

Мы заметили, что для каждого запроса (особенно для операторов SELECT) потребление памяти postgres.exe повышается. Он достигает 1,3 ГБ. В конце концов, postgres.exe вылетает из строя и заставляет нашу программу создавать новое соединение.

Неужели кто-нибудь испытал эту проблему раньше?

EDIT: shared_buffer в настоящее время установлен в 128MB в нашем conf. файл.

EDIT2: обходной путь, который мы имеем сейчас, - это вызвать PQfinish для каждой транзакции. Но тогда это немного замедляет нашу обработку с момента установления соединения каждый раз довольно медленно.

ответ

1

Использование памяти не обязательно является проблемой. PostgreSQL использует разделяемую память для некоторого кэширования, и эта память не учитывает размер использования памяти процесса до тех пор, пока она фактически не используется. Чем больше вы используете этот процесс, тем большую часть разделяемых буферов будут активны в его адресном пространстве.

Если у вас есть большое значение для shared_buffers, это произойдет. Если у вас это слишком большое, процесс может закончиться из адресного пространства и сбой, да.

+0

В настоящее время мы установили ее в 128 МБ, и это не мешает ей подняться выше 128 МБ. – sivabudh

+0

Это, безусловно, звучит хуже. Каковы ваши настройки для work_mem? –

4

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

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

Если вам нужно больше подключений, вы должны использовать прокси-сервер или систему пула, которая позволяет отделить «состояние соединения» от «механизма выполнения». Два популярных варианта: PgBouncer и PgPool-II. Вы можете поддерживать легкие подключения из своего приложения в прокси/пул, а также планировать рабочую нагрузку, чтобы сервер базы данных работал с оптимальной нагрузкой. Если приходит слишком много запросов, некоторые ждут перед выполнением, вместо того, чтобы конкурировать за ресурсы и замедлять все запросов на сервере.

См. postgresql wiki.

Обратите внимание, что если ваша рабочая нагрузка считывается главным образом, и особенно если у нее есть элементы, которые часто не меняются, для которых вы можете определить надежную схему cache invalidation, вы также можете использовать memcached или Redis для снижения нагрузки на базу данных. Для этого требуются изменения приложения. PostgreSQL LISTEN и NOTIFY помогут вам сделать недействительным кэш-память.

Многие двигатели базы данных имеют некоторое разделение механизма выполнения и состояния подключения, встроенного в конструкцию ядра базы данных.Sybase ASE конечно делает, и я думаю Oracle тоже, но я не слишком уверен в последнем. К сожалению, из-за модели однопроцессорного подключения PostgreSQL нелегко передать работу между бэкэндами, что затрудняет выполнение PostgreSQL изначально, поэтому большинство людей используют прокси-сервер или пул.

Настоятельно рекомендую вам прочитать PostgreSQL High Performance. У меня нет никаких отношений/принадлежности к Грегу Смиту или издателю *, я просто считаю, что это здорово и будет очень полезно, если вы будете обеспокоены работой вашего БД.


* ... ну, я не сделал, когда я писал это. Сейчас я работаю в той же компании.

0

Проблема, вероятно, в том, что вы не закрываете транзакцию, В PostgreSQL, даже если вы делаете только выбор без DML, он запускается в транзакции, которая должна быть откат. Добавив откат в конце транзакции, вы уменьшите проблему с памятью.

Смежные вопросы