PG数据库遇到内存问题要立即进行分析的场景并不多,因为大多数PG数据库的内存使用率过高的报警并不意味着内存使用情况异常,内存真的不够用了。因为PG数据库是使用DOUBLE BUFFERING机制的,大量的内存很可能被BUFFER/CACHE占用了。
上面的free命令可以看到32G内存使用了15G多,但是free只剩下599M了,BUFF/CACHE占了15G多。不过如果我们看available,有9G多,当前这个PG服务器的内存是充足的。从这个例子上看到,我们看fee命令的结果的时候,不应该看free,看available更为准确。
/proc/meminfo可以更详细的看到OS的内存情况,我们可以关注红框里的几个数字。Dirty是FILE CACHE中尚未写入磁盘的脏数据,是无法快速丢弃的内存,如果这个指标持续较高,那么说明OS的回写机制或者磁盘存在性能问题,是需要关注的。PageTalbes如果比较大,对于PG数据库来说,很可能是配置了较大的shared_buffers,但是没有启用HugePages,这样除了会影响PG数据库访问内存的性能外,还会占据大量的不必要的内存。AnonHugePages指标大于零说明没有关闭透明大页,而且已经使用了透明大页,对于PG、Oracle等数据库来说,透明大页的缺点大于优点,会引起内存碎片,建议关闭。另外需要关注的是SWAP的使用率,如果FREE内存很大,但是SWAP使用率超过20%,很可能是OS的NUMA内存方面的配置存在问题,没有全局分配内存。
遇到PG数据库的空闲内存不足的问题,首先通过这些机制分析OS内存是否真的存在风险,如果没有发现明显的风险,暂时就不需要做进一步的分析了。如果真的存在风险,我们还可以继续在OS层面查找。
ps aux –sort -rss |head -20命令可以查出rss使用最高的20个进程。然后找出存在问题的进程,用smem做进一步分析。
如果找到了存在问题的进程,可以用smem进一步去做分析。其中USS是进程私有内存,PSS是私有内存+共享内存的总和。
如果在OS层面找到了存在问题的进程,那么可以使用上面的语句去查找其PG会话的信息,进一步进行定位。一般情况下,PG会话占用较多的内存可能是做VACUUM、ANALYZE、排序,表连接、内存临时表等操作。
如果不存在某个进程使用内存过多,而是大量的进程都占用差不多的内存,那么很可能是数据库并发执行某类SQL,使用了排序,表连接等临时内存分配。这时候就要去分析数据库的性能是否存在问题,导致了某类SQL或者某条SQL并发执行量较大。亦或是某条SQL的执行计划出现了错误,导致执行时间过长,并发执行量过大,占用了大量物理内存。