查看PostgreSQL数据库进程占用内存的方法

前言

目前很多同学使用top命令查看内存时,会发现有一些PostgreSQL进程占用了很大的内存,用ps aux常看各个进程的内存时,如果把各个进程的内存加起来时,发现超过了总内存,所以很困惑。中启乘数科技做为专业的数据库服务提供商,对此问题有深入的研究,在这里给大家解惑。

原理解释

我们用top查看时,有时会看到某个PostgreSQL进程占用的内存很大,如下图所示:

查看PostgreSQL数据库进程占用内存的方法_第1张图片

从上图中可以看到进程(pid=45286)占到了机器总内存的25.9%,这台机器的总内存是128G,25.9%,基本就是33GB,从感觉上看觉得不可能?但是这里确实显示占用了这么大内存。进一步查看这个进程:

[root@pg01 ~]# ps -ef|grep 45286 |grep -v greppostgres 45286 45282  0  2020 ?        05:33:30 postgres: checkpointer

发现这个进程是checkpointer进程,难道有内存泄露?但是查看了很多长时间运行的PostgreSQL数据库,发现checkpointer进程都占用了很高的内存。实际上这里看到的这个内存并不是这个进程实际占用的真实内存。原因是这里显示的内存包括了共享内存,而共享内存是在很多的进程之间共享的,不能都算到这个进程头上。另我们知道PostgreSQL数据库使用了很大的共享内存,做数据块的缓存。查看数据库的参数shared_buffers看到数据库的共享内存的大小:

[postgres@pg01 ~]$ psqlpsql (11.7)Type "help" for help.postgres=# show shared_buffers; shared_buffers ---------------- 32GB(1 row)

我们有时也会用ps aux查看进程的内存,如下:

[root@pg01 ~]# ps aux --sort=-rss |head -10USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMANDpostgres 45286  0.0 25.8 35072428 33997064 ?   Ss    2020 333:30 postgres: checkpointer   postgres 45287  0.0  8.3 35067396 10929444 ?   Ss    2020  49:22 postgres: background writerpostgres 23784 30.4  0.8 35091120 1118520 ?    Rs   21:42   4:13 postgres: inofa greenerp2018 192.168.2.193(62975) SELECTpostgres 24074 41.8  0.8 35091636 1095144 ?    Rs   21:47   4:04 postgres: inofa greenerp2018 192.168.2.193(63056) SELECTpostgres 24737 38.2  0.8 35090844 1090260 ?    Rs   21:54   0:51 postgres: inofa greenerp2018 192.168.2.193(63202) SELECTpostgres 24837 70.3  0.8 35091552 1078752 ?    Rs   21:55   1:03 postgres: inofa greenerp2018 192.168.2.193(63223) SELECTpostgres 24368 44.3  0.8 35093552 1064208 ?    Rs   21:50   2:50 postgres: inofa greenerp2018 192.168.2.193(63124) SELECTpostgres 24835 52.3  0.8 35093740 1057660 ?    Rs   21:55   0:47 postgres: inofa greenerp2018 192.168.2.193(63222) SELECTpostgres 45282  0.0  0.8 35064744 1054188 ?    S     2020  84:47 /usr/pgsql-11.7/bin/postgres -D /data/ssd_pg_data/sale_pgdata_11

注意上图中的列VSZ是虚拟内存并不是实际占用的内存,RSS虽然是实际的内存,但是包括了共享的部分。而top命令中看到进程内存的百分比就是RSS内存占用总内存的百分比。

所以查看PostgreSQL进程占用的内存,正确的姿势应该是把共享的那部分内存给扣除掉,但是用ps命令没有办法扣除掉这部分内存。而实际上我们可以看/proc//smaps文件中查看Pss内存,Pss表示的内存是把共享内存平分到各个进程上的内存,这实际上是这个进程占用的实际内存:

[root@pg01 ~]# cat /proc/12047/smaps |more00400000-00ad1000 r-xp 00000000 fd:01 42123205                           /usr/pgsql-11.7/bin/postgresSize:               6980 kBRss:                 528 kBPss:                  67 kBShared_Clean:        512 kBShared_Dirty:          0 kBPrivate_Clean:        16 kBPrivate_Dirty:         0 kBReferenced:          528 kBAnonymous:             0 kBAnonHugePages:         0 kBSwap:                  0 kBKernelPageSize:        4 kBMMUPageSize:           4 kBLocked:                0 kBVmFlags: rd ex mr mw me dw sd 00cd0000-00cd1000 r--p 006d0000 fd:01 42123205                           /usr/pgsql-11.7/bin/postgresSize:                  4 kBRss:                   4 kBPss:                   0 kBShared_Clean:          0 kBShared_Dirty:          4 kBPrivate_Clean:         0 kBPrivate_Dirty:         0 kB.........

这个smaps看到的内存非常详细,有很多项,如果我们想查询出哪些进程占用内存多,不是很方便。

实际上CentOS7.X下提供了命令smem,可以方便的查看Pss内存。

使用smem查看进程占用的内存

smem工具可以方便的查看Pss内存,这个工具实际是一个python脚本。
smem工具一般默认都没有安装上,这个包是在EPEL扩展包中,所以需要先安装epel扩展包:

yum install -y epel-release

然后在安装smem:

 yum install -y smem

用smem命令查看占用内存最多的前20个进程:

[root@PG02 ~]# smem -t -r  | head -20  PID User     Command                         Swap      USS      PSS      RSS 12035 postgres postgres: startup   recover        0   120800  5012485 10186640 12047 postgres postgres: checkpointer             0   104684  4995433 10115820 12032 postgres /usr/pgsql-11.7/bin/postgre        0   510344   664110  1054460 28643 postgres postgres: inofa greenerp201        0   433236   512166   773388 27838 postgres postgres: inofa greenerp201        0    19568   282248   914964 27462 postgres postgres: inofa greenerp201        0    19820   279398   913364 27913 postgres postgres: inofa greenerp201        0    10812   271796   906096 12048 postgres postgres: background writer        0      168    68658   264096 27139 postgres postgres: inofa greenerp201        0    26880    67974   229700 27732 postgres postgres: inofa greenerp201        0    14272    36483   104760 27264 postgres postgres: inofa greenerp201        0    15512    29736    90616 28234 postgres postgres: inofa greenerp201        0    13904    23913    66956 27861 postgres postgres: inofa greenerp201        0     7216    21375    61788 27287 postgres postgres: inofa greenerp201        0     9236    18343    67220 28654 postgres postgres: inofa greenerp201        0     8124    15647    70764   493 root     /usr/lib/systemd/systemd-jo        0     5760    13507    27548  1211 root     ../pyenv/bin/python clup_ag        0    13424    13469    14524   780 root     /sbin/dhclient -d -q -sf /u        0    12484    12680    14824   887 postgres postgres: inofa greenerp201        0    10104    12438    35852

如果完全不包括共享部分的内存,可以看上面“USS”列显示的内存。

最后把几类内存的名词解释一下:

  • VSS- Virtual Set Size 虚拟内存(包含共享库占用的内存)
  • RSS- Resident Set Size 实际使用物理内存(包含共享库占用的内存)
  • PSS- Proportional Set Size 实际使用的物理内存(比例分配共享库占用的内存)
  • USS- Unique Set Size 进程独自占用的物理内存(不包含共享库占用的内存)

转自:https://www.cnblogs.com/zhenren001/p/17692828.html
http://pgsql.tech/supreme_101_10000109

你可能感兴趣的:(PostgreSQL,数据库,postgresql,oracle)