空闲的PostgreSQL进程占用大量内存

22

我正在尝试弄清楚为什么在正常使用后,约30个空闲的Postgres进程会占用如此多的进程特定内存。我正在使用Postgres 9.3.1和CentOS 6.3版本(最终版本)。 通过top命令,我可以看到许多Postgres连接正在使用高达300MB(平均约200MB)的非共享内存(RES-SHR):

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
 3534 postgres  20   0 2330m 1.4g 1.1g S  0.0 20.4   1:06.99 postgres: deploy mtalcott 10.222.154.172(53495) idle
 9143 postgres  20   0 2221m 1.1g 983m S  0.0 16.9   0:14.75 postgres: deploy mtalcott 10.222.154.167(35811) idle
 6026 postgres  20   0 2341m 1.1g 864m S  0.0 16.4   0:46.56 postgres: deploy mtalcott 10.222.154.167(37110) idle
18538 postgres  20   0 2327m 1.1g 865m S  0.0 16.1   2:06.59 postgres: deploy mtalcott 10.222.154.172(47796) idle
 1575 postgres  20   0 2358m 1.1g 858m S  0.0 15.9   1:41.76 postgres: deploy mtalcott 10.222.154.172(52560) idle

总共有29个空闲连接。这些空闲的连接会不断增长,直到机器开始使用交换空间,然后性能就会变得非常缓慢。

重置连接可以清除进程特定的内存,当我定期重新连接时,在同一台机器上相同数量的连接仅使用20%的内存(没有交换)。这些进程保存了什么样的信息?我希望长时间运行的空闲Postgres进程的内存使用与全新的空闲进程相似。

值得注意的是:我正在大量使用模式。在每次对我的应用程序的请求中,我都会设置和重置search_path。

1个回答

19
这些进程保存了什么样的信息?我原本以为运行时间长且空闲的Postgres进程与全新的空闲进程的内存使用情况类似。
实际上,Postgres会在加载后将许多内容缓存在本地内存中,其中包括:
- relcache(关系描述符) - catcache(系统目录条目) - 编译过的plpgsql函数树
对于大多数用例,所有这些都加起来只占微不足道的数量。关键在于模式的重度使用及其对relcache的影响。该数据库包含约500个模式,每个模式都有相同的约90个表。对于Postgres来说,即使所有模式都相同,这也相当于45000个表(500 * 90)。
每个请求都会将一些表的关系描述符缓存在内存中(通常位于前一个请求不同的模式中),逐渐填满relcache。不幸的是,Postgres没有提供限制这些缓存大小的方法,因为这可能会对大多数用例产生反作用。
可能的解决方案:
  • 在一定数量的请求后重新连接
  • 增加更多内存
  • 使用pgpool-IIPgBouncer进行连接池,将Postgres连接数限制在一个上限之内

感谢Tom Lane和Merlin Moncure在Postgres邮件列表中提供的帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接