PostgreSQL消耗大量内存以进行持久连接

时间:2009-08-01 05:15:42

标签: postgresql memory libpq

我有一个在Windows上使用PostgreSQL 8.3的C ++应用程序。我们使用libpq接口。

我们有一个多线程应用程序,每个线程打开一个连接,并在没有PQFinish的情况下继续使用。

我们注意到,对于每个查询(特别是SELECT语句),postgres.exe的内存消耗会增加。它高达1.3 GB。最终,postgres.exe崩溃并强制我们的程序创建一个新连接。

之前有没有人遇到过这个问题?

编辑:shared_buffer目前在我们的conf中设置为128MB。文件。

EDIT2:我们现在采用的解决方法是为每笔交易调用PQfinish。但是,这会减慢我们的处理速度,因为每次建立连接都很慢。

3 个答案:

答案 0 :(得分:4)

在PostgreSQL中,每个连接都有一个专用的后端。这个后端不仅保持连接和会话状态,而且还是一个执行引擎。留下后备并不是特别便宜,即使在闲置时也会花费内存和同步开销。

对于任何给定的Pg服务器,在任何给定的工作负载上都有最佳数量的主动工作后端,其中添加更多工作后端会减慢速度而不是加快速度。您希望找到该点,并将后端数量限制在该级别附近。不幸的是,这没有神奇的配方,它主要涉及基准测试 - 硬件和工作量。

如果您需要更多连接,则应使用允许您将“连接状态”与“执行引擎”分开的代理或池系统。两种流行的选择是PgBouncerPgPool-II。您可以保持从应用程序到代理/池的轻量级连接,并让它调度工作负载以使数据库服务器保持最佳负载。如果有太多查询进入,则有些人会在执行之前等待,而不是竞争资源并降低服务器上所有查询的速度。

请参阅postgresql wiki

请注意,如果您的工作负载主要是读取的,特别是如果它的项目不经常更改,您可以确定可靠的cache invalidation方案,那么您还可以使用memcached或Redis来减少数据库工作量这需要更改应用程序。 PostgreSQL的LISTENNOTIFY将帮助您进行合理的缓存失效。

许多数据库引擎都将内置的执行引擎和连接状态分离到核心数据库引擎的设计中。 Sybase ASE确实如此,而且我认为 Oracle也是如此,但我对后者不太了解。不幸的是,由于PostgreSQL的单进程每个连接模型,它不容易在后端之间传递解决方案,使得PostgreSQL更难以本地执行此操作,因此大多数人使用代理或池。

我强烈建议您阅读PostgreSQL High Performance。我与Greg Smith或出版商 * 没有任何关系/联系,我认为这很好,如果您担心自己的数据库表现会非常有用。


* ......好吧,我写这篇文章的时候并没有。我现在在同一家公司工作。

答案 1 :(得分:1)

内存使用不一定是个问题。 PostgreSQL使用共享内存进行一些缓存,并且在实际使用之前,此内存不会计入进程内存使用量的大小。您使用该过程的次数越多,共享缓冲区的较大部分将在其地址空间中处于活动状态。

如果 shared_buffers 的值很大,则会发生这种情况。如果它太大,那么进程可能会耗尽地址空间并崩溃,是的。

答案 2 :(得分:0)

问题可能是你没有关闭交易, 在PostgreSQL中,即使您只选择没有DML,它也会在需要回滚的事务中运行。 通过在事务结束时添加回滚将减少内存问题