2013-12-11 119 views
18

我想弄清楚为什么~30空闲postgres进程在正常使用后占用大量进程特定的内存。我正在使用Postgres 9.3.1和CentOS 6.3版(最终版)。 使用top,我可以看到,许多Postgres连接的非共享(RES - SHR)是使用高达300MB(平均〜200MB)存储器:空闲postgres进程占用大量内存

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。

回答

12

这些过程持有什么样的信息?我希望长期运行的闲置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的帮助。