合 PG数据库配置大页
Linux 标准大页和透明大页参考:https://www.dbaup.com/linux-biaozhundayehetoumingdaye.html
为了保证物理内存能得到充分的利用,避免内存空间浪费,Linux把进程当前使用的内存部分加载到物理内存里,而不使用的部分则暂不加载。PostMaster进程注册共享内存时,系统只是分配一个虚拟的地址空间,并不直接分配物理内存。当有实际的内存访问时,CPU才会将虚拟地址映射到物理内存的一个地址上。维护这个映射关系的就是PageTable,它负责将虚拟内存地址转换成物理内存地址。
Linux的内存管理采取的是分页存取机制:把较大的物理内存分为了一个个固定大小(4kB)的内存页进行管理。每块内存页通过PageTable中的一个元组来维护虚拟/物理内存之间的映射。CPU为了提高虚拟/物理内存之间的转换效率,也会在TLB中缓存一定量的Page Table元组。
对于PostgreSQL这种多进程架构程序来说,当服务端使用的共享内存较大,且并发连接数较多时,由于操作系统对于每个进程都要维护单独的内存映射,PageTable中的元组数目将会变得非常多,所占用的内存大小也会特别大。
Linux为了应对这种场景,降低多进程下PageTable的内存消耗。自从2.6及以上内核版本提供了内存页大小为2MB的管理方式,称为Huge Page。如果使用Huge Page的话,相同物理内存使用量的情况下内存页的数目变少,减少了PageTable元组的条目个数,从而降低了系统的内存占用。
真实应用场景:某PG用户将实例(shared_buffers = 64GB)部署在一台内存为256GB的ECS上,业务繁忙时ECS内存使用率为85%,PageTable占用内存120GB。而开启Huge Page后相同业务场景的内存使用率降低到50%以下,PageTable大小仅300M!
PG从9.4版本开始支持大页,对一些连接数很大且内存较大的PostgreSQL数据库,强烈建议配置大页( Huge pages )。这不仅仅是因为大页的性能会高一些,也是为了避免页表过大。
PG配置大页
当PostgreSQL使用大量连续的内存块时,使用大页面会减少开销, 特别是在使用大shared_buffers时。 要在PostgreSQL中使用此特性,您需要一个包含 CONFIG_HUGETLBFS=y
和CONFIG_HUGETLB_PAGE=y
的内核。 您还必须调整内核设置vm.nr_hugepages
。要估计所需的大页面的数量, 请启动PostgreSQL,而不启用大页面,并使用 /proc
文件系统来检查postmaster的匿名共享内存段大小以及系统的大页面大小。
计算nr_hugepages数量
例如:
1 2 3 4 5 6 | $ head -1 $PGDATA/postmaster.pid 4170 $ pmap 4170 | awk '/rw-s/ && /zero/ {print $2}' 6490428K $ grep ^Hugepagesize /proc/meminfo Hugepagesize: 2048 kB |
6490428
/ 2048
大约是3169.154
,因此在这个示例中你至少需要 3170
个大页面,我们可以设置:
1 | $ sysctl -w vm.nr_hugepages=3170 |
如果机器上的其他程序也需要大页面,则更大的设置将是合适的。
也可以基于如下脚本直接计算相应的HugePage的大小。
1 2 3 4 5 6 7 8 9 10 11 12 13 | #!/bin/bash PGDATA="/pg13/pgdata" pid=`head -1 $PGDATA/postmaster.pid` echo "Pid: $pid" peak=`grep ^VmPeak /proc/$pid/status | awk '{ print $2 }'` echo "VmPeak: $peak kB" hps=`grep ^Hugepagesize /proc/meminfo | awk '{ print $2 }'` echo "Hugepagesize: $hps kB" hp=$((peak/hps)) echo Set Huge Pages: $hp sysctl -w vm.nr_hugepages=$hp |
这种配置一般针对于数据库服务器,就是只跑了个PostgreSQL,如果还有其他应用程序也需要大页,则需要合理设置。
不要忘记将此设置添加到/etc/sysctl.conf
, 以便在重启后重新应用它。
1 2 3 4 5 6 7 8 9 | echo 3170 > /proc/sys/vm/nr_hugepages cat >> /etc/sysctl.conf <<"EOF" vm.nr_hugepages=3170 EOF sysctl -p |
通过此脚本计算出大页的大小,然后添加到/etc/sysctl.conf里,sysctl -p生效。
配置参数huge_pages为try
PostgreSQL中大页面的默认行为是 尽可能使用它们并且在失败时转回到正常页面。要强制使用大页面,你可 以在postgresql.conf
中把huge_pages
设置成 on
。注意此设置下如果没有足够的大页面可用, PostgreSQL将会启动失败。一般建议默认值try即可。
1 2 3 4 5 6 | postgres=# show huge_pages; huge_pages ------------ try (1 row) |
然后重新启动PG数据库。
查询
有时候内核会无法立即分配想要数量的大页面,所以可能有必要重复该命令或者重新启动。 在重新启动之后,会立即将大部分机器的内存转换为大页面。
要验证巨大的页面分配情况,请使用:
1 2 3 4 5 6 7 | [pg13@lhrpg pgdata]$ cat /proc/meminfo | grep huge -i AnonHugePages: 243712 kB HugePages_Total: 300 HugePages_Free: 144 HugePages_Rsvd: 73 HugePages_Surp: 0 Hugepagesize: 2048 kB |