# 19.4.管理内核资源

19.4.1. 共享内存和信号量

19.4.2. 系统删除PC

19.4.3. 资源限制

19.4.4. Linux内存过度使用

19.4.5. Linux巨大的页面

PostgreSQL有时会耗尽各种操作系统资源限制,尤其是当服务器的多个副本在同一个系统上运行时,或者在非常大的安装中。本节介绍PostgreSQL使用的内核资源,以及解决与内核资源消耗相关的问题时可以采取的步骤。

# 19.4.1.共享内存和信号量

PostgreSQL要求操作系统提供进程间通信(IPC)功能,特别是共享内存和信号量。Unix衍生系统通常提供“System V”IPC、“POSIX”IPC,或两者兼备。Windows有自己的这些功能的实现,这里不讨论。

默认情况下,PostgreSQL会分配非常少量的System V共享内存,以及更大量的匿名内存mmap共享内存。或者,可以使用单个大型System V共享内存区域(参见共享_记忆力_类型).此外,大量信号量可以是System V或POSIX样式,都是在服务器启动时创建的。目前,POSIX信号量用于Linux和FreeBSD系统,而其他平台使用SystemV信号量。

System V IPC功能通常受系统范围的分配限制。当PostgreSQL超过其中一个限制时,服务器将拒绝启动,并应留下一条指示性错误消息,描述问题以及如何解决。(另见第19.3.1节)相关的内核参数在不同的系统中统一命名;表19.1给出了一个概述。然而,设置它们的方法各不相同。下面给出了一些平台的建议。

表19.1.系统V IPC参数

名称 描述 运行一个PostgreSQL实例所需的值
什玛克斯 共享内存段的最大大小(字节) 至少1kB,但默认值通常要高得多
什敏 共享内存段的最小大小(字节) 1.
SHMALL 可用共享内存总量(字节或页面) 等同于什玛克斯如果是字节,或天花板(最大/页面大小)如果有页面,还有其他应用程序的空间
SHMSEG 每个进程的最大共享内存段数 只需要1个段,但默认值要高得多
什姆尼 系统范围内共享内存段的最大数量 喜欢SHMSEG还有其他应用的空间
塞姆尼 信号量标识符的最大数量(即集合) 至少ceil((最大连接数+自动吸尘器最大工作人员数+最大工作人员数+最大发送者数+最大工作人员数+5)/16)还有其他应用的空间
SEMMNS 系统范围内信号灯的最大数量 ceil((最大连接数+自动吸尘器最大工人数+最大墙壁发送器数+最大工人数+流程数+5)/16)*17还有其他应用的空间
SEMMSL 每组信号灯的最大数量 至少17岁
SEMMAP 信号量映射中的条目数 见正文
SEMVMX 信号量最大值 至少1000(默认值通常为32767;除非必要,否则不要更改)

PostgreSQL需要为服务器的每个副本提供几个字节的System V共享内存(在64位平台上通常为48字节)。在大多数现代操作系统上,这个数量可以很容易地分配。但是,如果您正在运行服务器的多个副本,或者明确地将服务器配置为使用大量System V共享内存(请参阅)共享_记忆力_类型动态_共享_记忆力_类型),可能有必要增加SHMALL,这是System V系统范围内共享内存的总量。注意SHMALL在许多系统中,以页面而不是字节来度量。

导致问题的可能性较小的是共享内存段的最小大小(什敏),对于PostgreSQL,它最多应该是大约32个字节(通常只有1个字节)。系统范围内的最大分段数(什姆尼)或每道工序(SHMSEG)除非系统将它们设置为零,否则不太可能导致问题。

当使用SystemV信号量时,PostgreSQL在每个允许的连接中使用一个信号量(最大值_连接),允许自动真空工作过程(自动真空_最大值_工人)并允许后台处理(最大值_工人_过程),一套16件。每个这样的集合还将包含第17个信号量,其中包含一个“幻数”,用于检测与其他应用程序使用的信号量集合的冲突。系统中信号量的最大数量由SEMMNS,因此必须至少达到max_连接自动吸尘器max_wal_sendersmax_worker_进程,每16个允许的连接点加上一个额外的工人(见中的公式)表19.1).参数塞姆尼确定系统上一次可以存在的信号量集的数量限制。因此,该参数必须至少为ceil((最大连接数+自动吸尘器最大工作人员数+最大工作人员数+最大发送者数+最大工作人员数+5)/16).减少允许的连接数是解决功能故障的一个临时解决办法,通常会被混淆为“设备上没有剩余空间”塞姆杰.

在某些情况下,可能还需要增加SEMMAP至少在SEMMNS。如果系统有此参数(许多没有),它将定义信号量资源映射的大小,其中每个连续的可用信号量块都需要一个条目。当信号量集被释放时,它要么被添加到与被释放块相邻的现有条目中,要么被注册到新的映射条目下。如果映射已满,则释放的信号量将丢失(直到重新启动)。随着时间的推移,信号量空间的碎片化可能会导致可用信号量的减少。

与“信号量撤消”相关的各种其他设置,例如塞姆努SEMUME,不影响PostgreSQL。

使用POSIX信号量时,所需的信号量数量与System V相同,即每个允许的连接一个信号量(最大值_连接),允许自动真空工作过程(自动真空_最大值_工人)并允许后台处理(最大值_工人_过程).在首选此选项的平台上,POSIX信号量的数量没有特定的内核限制。

艾克斯

无需对以下参数进行任何特殊配置:什玛克斯,它似乎被配置为允许所有内存用作共享内存。这种配置通常用于其他数据库,如DB/2.

然而,可能有必要修改全局变量文件描述符信息在/etc/安全/限制,作为文件大小的默认硬限制(fsize)以及文件的数量(无文件)可能太低了。

FreeBSD

默认的共享内存设置通常足够好,除非您设置了共享内存类型sysv.此平台上不使用System V信号量。

默认的IPC设置可以使用系统控制装载机接口。以下参数可以使用系统控制:

# sysctl kern.ipc.shmall=32768
# sysctl kern.ipc.shmmax=134217728

要使这些设置在重新启动时保持不变,请修改/etc/sysctl。形态.

如果你已经准备好了共享内存类型sysv,您可能还希望将内核配置为将SystemV共享内存锁定到RAM中,并防止它被调出以进行交换。这可以通过使用系统控制背景克恩。ipc。shm_使用物理.

如果在FreeBSD监狱里跑步,你应该设置sysvshm参数到,这样它就有了自己独立的System V共享内存命名空间。(在FreeBSD 11.0之前,有必要从监狱中启用对主机IPC命名空间的共享访问,并采取措施避免冲突。)

NetBSD

默认的共享内存设置通常足够好,除非您设置了共享内存类型sysv.你通常会想增加克恩。ipc。塞姆尼克恩。ipc。semmns,因为NetBSD的默认设置非常小。

IPC参数可以使用系统控制,例如:

# sysctl -w kern.ipc.semmni=100

要使这些设置在重新启动时保持不变,请修改/etc/sysctl。形态.

如果你已经准备好了共享内存类型sysv,您可能还希望将内核配置为将SystemV共享内存锁定到RAM中,并防止它被调出以进行交换。这可以通过使用系统控制背景克恩。ipc。shm_使用物理.

OpenBSD

默认的共享内存设置通常足够好,除非您设置了共享内存类型sysv.你通常会想增加克恩。塞米福。塞姆尼克恩。塞米福。semmns,因为OpenBSD的默认设置非常小。

IPC参数可以使用系统控制,例如:

# sysctl kern.seminfo.semmni=100

要使这些设置在重新启动时保持不变,请修改/etc/sysctl。形态.

HP-UX

默认设置往往足以进行正常安装。

IPC参数可以在内核配置下的系统管理管理器(SAM)中设置→ 可配置参数。完成后选择创建一个新内核。

Linux

默认的共享内存设置通常足够好,除非您设置了共享内存类型sysv,即使如此,也只适用于默认值较低的旧内核版本。System V信号量不在此平台上使用。

共享内存大小设置可以通过系统控制界面例如,要允许16 GB:

$ sysctl -w kernel.shmmax=17179869184
$ sysctl -w kernel.shmall=4194304

要使这些设置在重新启动时保持不变,请参阅/etc/sysctl。形态.

马科斯

默认的共享内存和信号量设置通常足够好,除非您设置了共享内存类型sysv.

在macOS中配置共享内存的推荐方法是创建一个名为/etc/sysctl。形态,包含变量赋值,例如:

kern.sysv.shmmax=4194304
kern.sysv.shmmin=1
kern.sysv.shmmni=32
kern.sysv.shmseg=8
kern.sysv.shmall=1024

请注意,在某些macOS版本中,五个人必须在中设置共享内存参数/etc/sysctl。形态,否则这些值将被忽略。

什玛克斯只能设置为4096的倍数。

SHMALL在这个平台上以4KB的页面计算。

除此之外,一切都有可能改变什姆尼在运行中,使用sysctl。但最好还是通过/etc/sysctl。形态,以便在重新启动期间保持这些值。

Solaris
illumos

对于大多数PostgreSQL应用程序来说,默认的共享内存和信号量设置通常足够好。Solaris默认为什玛克斯占系统RAM的四分之一。要进一步调整此设置,请使用与博士后使用者例如,按以下步骤运行:

projadd -c "PostgreSQL DB User" -K "project.max-shm-memory=(privileged,8GB,deny)" -U postgres -G postgres user.postgres

此命令添加使用者博士后项目并设置共享内存的最大值博士后将用户设置为8GB,并在用户下次登录或重新启动PostgreSQL(而不是重新加载)时生效。以上假设PostgreSQL由博士后中的用户博士后组不需要重新启动服务器。

对于将有大量连接的数据库服务器,其他建议的内核设置更改包括:

project.max-shm-ids=(priv,32768,deny)
project.max-sem-ids=(priv,4096,deny)
project.max-msg-ids=(priv,4096,deny)

此外,如果在区域内运行PostgreSQL,可能还需要提高区域资源使用限制。请参阅中的“第2章:项目和任务”系统管理员指南有关项目prctl.

# 19.4.2.系统删除PC

如果正在使用systemd,则必须注意操作系统不会过早删除IPC资源(包括共享内存)。从源代码安装PostgreSQL时,这一点尤其值得关注。PostgreSQL发行包的用户受影响的可能性较小,因为博士后然后,用户通常被创建为系统用户。

背景移除在里面登录。形态控制用户完全注销时是否删除IPC对象。系统用户是免税的。在stock systemd中,此设置默认为on,但某些操作系统发行版将其默认为off。

打开此设置时,观察到的一个典型效果是,用于并行查询执行的共享内存对象在明显随机的时间被删除,导致在尝试打开和删除它们时出现错误和警告,如

WARNING:  could not remove shared memory segment "/PostgreSQL.1450751626": No such file or directory

systemd对不同类型的IPC对象(共享内存与信号量、系统V与POSIX)的处理略有不同,因此人们可能会注意到,某些IPC资源的删除方式与其他IPC资源不同。但依靠这些细微的差别是不可取的。

“用户注销”可能是维护作业的一部分,也可能是管理员以管理员身份登录时手动执行的博士后用户或类似的东西,所以一般来说很难预防。

什么是“系统用户”在systemd编译时由系统UID最大值开始/etc/登录。藐视.

打包和部署脚本在创建博士后用户作为系统用户使用useradd-r, adduser——系统,或同等标准。

或者,如果用户帐户创建不正确或无法更改,建议设置

RemoveIPC=no

在里面/etc/systemd/logind。形态或其他适当的配置文件。

# 小心

至少必须确保这两件事中的一件,否则PostgreSQL server将非常不可靠。

# 19.4.3.资源限制

类Unix操作系统强制执行各种资源限制,这些限制可能会干扰PostgreSQL server的操作。特别重要的是限制每个用户的进程数、每个进程打开的文件数以及每个进程可用的内存量。每个都有“硬”和“软”限制。软限制才是真正重要的,但用户可以更改到硬限制。硬限制只能由root用户更改。系统调用塞特利特负责设置这些参数。shell的内置命令文件描述符(伯恩贝壳)或限度(csh)用于从命令行控制资源限制。在BSD派生系统上,文件/etc/登录。形态控制登录期间设置的各种资源限制。有关详细信息,请参阅操作系统文档。相关参数如下:进程数上线, 开放文件数据大小.例如:

default:\
...
        :datasize-cur=256M:\
        :maxproc-cur=256:\
        :openfiles-cur=256:\
...

(-cur是软限制。追加-麦克斯设置硬限制。)

内核对某些资源也有系统范围的限制。

  • 在Linux上/proc/sys/fs/file max确定内核将支持的最大打开文件数。可以通过在文件中写入不同的数字或在文件中添加赋值来更改/etc/sysctl。形态.在编译内核时,每个进程的最大文件限制是固定的;看见/usr/src/linux/Documentation/proc。txt了解更多信息。

    PostgreSQL server每个连接使用一个进程,因此除了系统其余部分所需的进程之外,还应提供至少与允许的连接数量相同的进程。这通常不是问题,但如果在一台机器上运行多台服务器,事情可能会变得紧张。

    工厂对打开文件的默认限制通常设置为“社交友好”值,允许许多用户在一台机器上共存,而不使用不适当的系统资源。如果你在一台机器上运行多台服务器,这可能是你想要的,但是在专用服务器上,你可能想要提高这个限制。

    另一方面,一些系统允许单个进程打开大量文件;如果超过几个进程这样做,那么很容易超过系统范围的限制。如果发现这种情况,并且不想更改系统范围的限制,可以设置PostgreSQL的最大值_文件夹_每_过程用于限制打开文件的使用的配置参数。

# 19.4.4.Linux内存过度使用

Linux上的默认虚拟内存行为对于PostgreSQL来说不是最优的。由于内核实现内存过度分配的方式,如果PostgreSQL或其他进程的内存需求导致系统耗尽虚拟内存,内核可能会终止PostgreSQL postmaster(管理服务器进程)。

如果发生这种情况,您将看到一条如下所示的内核消息(请参阅系统文档和配置,了解在何处查找此类消息):

Out of Memory: Killed process 12345 (postgres).

这表明博士后由于内存压力,进程已终止。尽管现有数据库连接将继续正常工作,但不会接受新的连接。要恢复,需要重新启动PostgreSQL。

避免此问题的一种方法是在可以确保其他进程不会耗尽内存的机器上运行PostgreSQL。如果内存紧张,增加操作系统的交换空间有助于避免问题,因为只有在物理内存和交换空间耗尽时才会调用内存不足(OOM)杀手。

如果PostgreSQL本身是导致系统内存不足的原因,您可以通过更改配置来避免该问题。在某些情况下,它可能有助于降低与内存相关的配置参数,尤其是共享缓冲区, 工作记忆hash_mem_乘法器。在其他情况下,问题可能是由于允许太多连接到数据库服务器本身。在许多情况下,减少压力可能更好max_连接而是使用外部连接池软件。

可以修改内核的行为,使其不会“过度使用”内存。尽管此设置不会阻止OOM杀手 (opens new window)从完全被调用,它将大大降低机会,因此将导致更健壮的系统行为。这是通过以下方式实现的:通过系统控制:

sysctl -w vm.overcommit_memory=2

或者在/etc/sysctl。形态。您可能还希望修改相关设置虚拟机。超密比。有关详细信息,请参阅内核文档文件https://www.kernel.org/doc/Documentation/vm/overcommit-accounting (opens new window).

另一种方法,可以使用,也可以不修改虚拟机。过度限制记忆,是设置特定的流程OOM分数调整邮局主管流程的值-1000从而保证它不会成为OOM杀手的目标。最简单的方法就是执行

echo -1000 > /proc/self/oom_score_adj

在调用postmaster之前的postmaster启动脚本中。请注意,此操作必须以root用户身份执行,否则将无效;因此,根用户拥有的启动脚本是最容易做到这一点的地方。如果这样做,在调用邮局主管之前,还应该在启动脚本中设置以下环境变量:

export PG_OOM_ADJUST_FILE=/proc/self/oom_score_adj
export PG_OOM_ADJUST_VALUE=0

这些设置将导致postmaster子进程在正常OOM分数调整为零的情况下运行,这样OOM杀手仍然可以根据需要将其作为目标。你可以用一些其他的价值PG_OOM_调整_值如果希望子进程与其他OOM分数调整一起运行。(PG_OOM_调整_值也可以省略,在这种情况下,它默认为零。)如果你不设定PG_OOM_ADJUST_文件,子进程将以与邮政局长相同的OOM分数调整运行,这是不明智的,因为整个要点是确保邮政局长具有优先设置。

# 19.4.5.Linux巨大的页面

使用大型页面可以减少使用大型连续内存块时的开销,正如PostgreSQL所做的那样,尤其是在使用大型内存块时共享_缓冲区.要在PostgreSQL中使用此功能,您需要一个具有CONFIG_HUGETLBFS=yCONFIG_HUGETLB_PAGE=y。您还必须配置操作系统,以提供足够大的所需大小的页面。要估计所需的巨大页面数,请在不启用巨大页面的情况下启动PostgreSQL,并使用/过程/系统文件系统。这可能看起来像:

$ head -1 $PGDATA/postmaster.pid
4170
$ pmap 4170 | awk '/rw-s/ && /zero/ {print $2}'
6490428K
$ grep ^Hugepagesize /proc/meminfo
Hugepagesize:       2048 kB
$ ls /sys/kernel/mm/hugepages
hugepages-1048576kB  hugepages-2048kB

在本例中,默认值为2MB,但也可以使用巨大的_页_大小.假设2MB巨大的页面,6490428 / 2048大概3169.154所以在这个例子中,我们至少需要3170巨大的页面。如果机器上的其他程序也需要巨大的页面,则更大的设置是合适的。我们可以将其设置为:

# sysctl -w vm.nr_hugepages=3170

别忘了将此设置添加到/etc/sysctl。形态以便在重新启动后重新应用。对于非默认的巨大页面大小,我们可以使用:

# echo 3170 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages

还可以在引导时使用内核参数(如hugepagesz=2M hugepages=3170.

有时,由于碎片,内核无法立即分配所需数量的巨大页面,因此可能需要重复该命令或重新启动。(重启后,机器的大部分内存应该可以立即转换为巨大的页面。)要验证给定大小的巨大页面分配情况,请使用:

$ cat /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages

还可能需要通过设置数据库服务器的操作系统用户权限来使用大型页面虚拟机。hugetlb_shm_集团通过sysctl,和/或授予使用ulimit-l.

PostgreSQL中巨大页面的默认行为是在可能的情况下使用它们,使用系统默认的巨大页面大小,并在出现故障时返回到正常页面。要强制使用大型页面,可以设置巨大的_页在…上在里面postgresql。形态。请注意,如果没有足够的大页面可用,使用此设置,PostgreSQL将无法启动。

有关Linux巨大页面功能的详细描述,请参阅https://www.kernel.org/doc/Documentation/vm/hugetlbpage.txt (opens new window).