闲置的postgres进程占用了大量的内存

时间:2013-12-11 08:52:21

标签: postgresql memory centos centos6 postgresql-9.3

我试图弄清楚为什么~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%的内存(0交换)。这些流程持有什么样的信息?我希望长时间运行的闲置postgres进程能够拥有与全新闲置进程类似的内存使用情况。

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

1 个答案:

答案 0 :(得分:13)

  

这些流程持有哪些信息?我希望长时间运行的闲置postgres进程能够拥有与全新闲置进程类似的内存使用情况。

实际上,Postgres加载后会在本地内存中缓存一些东西:

  • relcache(关系描述符)
  • catcache(系统目录条目)
  • 为plpgsql函数编译树

对于大多数用例,所有这些都加起来可以忽略不计。这里的关键是模式的大量使用和对relcache的影响。该数据库包含~500个模式,每个模式具有相同的~90个表。对于Postgres,即使模式完全相同,这也可以达到45,000个表(500 * 90)。

每个请求都会在内存中缓存一些表的关系描述符(通常在与之前的请求不同的模式中),逐渐填满relcache。不幸的是,Postgres does not offer a way to limit the size of these caches,因为开销可能会对大多数用例产生反作用。

可能的解决方案:

  • 在一定数量的请求后重新连接
  • 添加更多内存
  • 连接池,使用pgpool-IIPgBouncer
  • 对postgres连接数量设置上限

感谢Tom Lane和Merlin Moncure在Postgres mailing lists上的帮助。