↑↓ 选择 ↵ 打开 ⌫ 改范围 完整检索页

pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。

受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
测试与开发版本: 19 / devel
不受支持的版本: 13 / 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0 / 7.4 / 7.3 / 7.2 / 7.1
历史版本PostgreSQL 7.4 已于 2010 年 10 月结束社区维护,本页译文保留供仍在使用旧版本的读者参考。新系统请看当前版本。

16.5. 管理内核资源 #

一个大型PostgreSQL安装会很快耗尽各种操作系统资源 限制。(在某些系统上,出厂默认值非常低,你甚至不需要真正 “大型”的安装就会遇到问题。)如果你遇到过这类问题, 请继续阅读。

16.5.1. 共享内存和信号量 #

共享内存和信号量统称为“System V IPC”(连同消息队列,但消息队列与 PostgreSQL无关)。几乎所有现代操作系统都提供这些 特性,但并非所有系统都默认启用了它们或将其设置得足够大,尤其是 有 BSD 血统的系统。(对于 QNX 和 BeOS 移植,PostgreSQL 为这些设施提供了自己的替代实现。)

完全缺少这些功能时,通常会在服务器启动时出现 Illegal system call 错误。在这种情况下,除了重新配置 内核别无选择。没有它们,PostgreSQL 无法工作。

当PostgreSQL超出各种硬性IPC限制 之一时,服务器会拒绝启动,并应留下带有指导性的错误消息,说明所 遇到的问题以及应如何处理(另见第 16.3.1 节)。相关内核参数在不同系统上的 命名基本一致,表 16.2给出了概览。不过, 设置它们的方法却各不相同。下面给出一些平台上的建议。请注意,更改 这些设置通常需要重启机器,甚至可能需要重新编译内核。

表 16.2. System V IPC参数

名称 描述 合理的值
SHMMAX 共享内存段的最大尺寸(字节) 250 kB + 8.2 kB * shared_buffers + 14.2 kB * max_connections,直至无穷大
SHMMIN 共享内存段的最小尺寸(字节) 1
SHMALL 可用共享内存的总量(字节或页面) 如果是字节,同SHMMAX;如果是页面,为ceil(SHMMAX/PAGE_SIZE)
SHMSEG 每个进程的最大共享内存段数目 只需要 1 段,但是默认值高很多
SHMMNI 系统范围内的最大共享内存段数目 像SHMSEG外加其他应用的空间
SEMMNI 信号量标识符(即,集合)的最大数目 至少 ceil(max_connections / 16)
SEMMNS 系统范围内的最大信号量数目 ceil(max_connections / 16) * 17,并为其他应用保留空间
SEMMSL 每个集合中信号量的最大数目 至少 17
SEMMAP 信号量映射中的项数 见文本
SEMVMX 信号量的最大值 至少 1000(默认值常常是 32767,如非必要不要更改)

最重要的共享内存参数是 SHMMAX,即以字节计的共享内存段的最大尺寸。如果 shmget返回像Invalid argument这样的错误 消息,可能是超出了这个限制。所需共享内存段的尺寸随请求的缓冲区 数量(-B 选项)和允许的连接数量(-N 选项) 而变化,尽管前者的影响最大。(作为临时解决办法,你可以调低这些 设置来消除失败。)粗略估计,你可以用缓冲区数量乘以块大小(默认 8 kB)再加上充足的额外开销(至少半兆字节)来估算所需的段尺寸。 你可能得到的任何错误消息都会包含失败分配请求的尺寸。

不太可能出问题的是共享内存段的最小尺寸(SHMMIN), 对PostgreSQL来说应该最多大约是 256 kB(通常只是 1)。系统范围(SHMMNI)或每进程 (SHMSEG)的最大共享内存段数目不会导致问题,除非你的 系统把它们设成零。有些系统还对系统内共享内存的总量有限制;参见 下面的平台特定说明。

PostgreSQL为每个允许的连接(-N 选项) 使用一个信号量,每 16 个组成一组。每组还包含第 17 个信号量,其中 存放一个“魔数”,用来检测与其他应用程序使用的信号量集 的冲突。系统中的信号量最大数量由SEMMNS设置,因此它 必须至少等于max_connections再加上每 16 个允许连接一个 的额外信号量(见表 16.2中的公式)。 参数SEMMNI决定系统中同时可以存在的信号量集的数量上限, 因此它必须至少为ceil(max_connections / 16)。降低 允许的连接数是失败时的一种临时变通办法,这种失败通常表现为 semget函数返回措辞令人困惑的No space left on device。

在某些情况下,可能还需要增大SEMMAP,使其至少与 SEMMNS处于同一数量级。这个参数定义信号量资源映射的 大小,映射中每个连续的可用信号量块都需要占用一项。每当一个信号量 集合被释放时,它要么会并入与该释放块相邻的现有项,要么会登记为一 个新的映射项。如果映射已满,被释放的信号量就会丢失(直到重启)。 信号量空间的碎片化随时间推移可能导致可用信号量少于应有数量。

SEMMSL参数决定一个信号量集中可以包含多少个信号量, 对于PostgreSQL,它必须至少为 17。

与“信号量撤销”有关的其他各种设置,如SEMMNU 和SEMUME,对PostgreSQL无关紧要。

BSD/OS

共享内存.  默认只支持 4 MB 共享内存。请记住,共享内存是不可换页的,它被 锁定在 RAM 中。要增加系统支持的共享内存量,可以在内核配置 文件中加入下面的内容。SHMALL值 1024 表示 4 MB 共享内存。以下设置把最大共享内存区域增加到 32 MB:

options "SHMALL=8192"
options "SHMMAX=\(SHMALL*PAGE_SIZE\)"

对于运行 4.3 或更高版本的用户,可能还需要把 KERNEL_VIRTUAL_MB增加到默认值248 之上。所有修改完成后,重新编译内核并重启。

对于运行 4.0 及更早版本的用户,可用bpatch在当前 内核中找到sysptsize值。该值是在引导时动态计算的。

$ bpatch -r sysptsize
0x9 = 9

然后,在内核配置文件中把SYSPTSIZE加为硬编码值。 把你用bpatch找到的值增大。每想要 4 MB 额外共享 内存就加 1。

options "SYSPTSIZE=16"

sysptsize无法通过sysctl更改。

信号量.  你可能需要增加信号量的数量。默认情况下, PostgreSQL分配 34 个信号量,这超过了系统默认 总数 60 的一半。请在内核配置文件中设置你想要的值,例如:

options "SEMMNI=40"
options "SEMMNS=240"
FreeBSD
NetBSD
OpenBSD

编译内核时需要启用选项SYSVSHM和SYSVSEM (默认已启用)。共享内存的最大尺寸由选项 SHMMAXPGS(以页计)决定。下面展示了一个如何设置 各参数的例子:

options         SYSVSHM
options         SHMMAXPGS=4096
options         SHMSEG=256

options         SYSVSEM
options         SEMMNI=256
options         SEMMNS=512
options         SEMMNU=256
options         SEMMAP=256

(在NetBSD和 OpenBSD上,关键字实际上是单数 形式的option。)

你可能还希望配置内核,把共享内存锁定在 RAM 中,防止其被换出 到交换区。这可以通过 sysctl 设置 kern.ipc.shm_use_phys 来实现。

HP-UX

默认设置通常足以满足普通安装的需求。在 HP-UX 10 上,SEMMNS 的出厂默认值为 128,对较大的数据库 站点来说可能过低。

可以在 System Administration Manager(SAM)的 Kernel Configuration → Configurable Parameters 中设置 IPC 参数。完成后选择 Create A New Kernel。

Linux

在 2.2 内核中,默认的共享内存限制 (SHMMAX和SHMALL都是) 是 32 MB,但可以在 proc 文件系统中更改 (无需重启)。例如,要允许 128 MB:

$ echo 134217728 >/proc/sys/kernel/shmall
$ echo 134217728 >/proc/sys/kernel/shmmax

你可以把这些命令放进引导时运行的脚本中。

另外,如果可用的话,也可以用sysctl控制这些 参数。找到名为/etc/sysctl.conf的文件,向 其中加入如下行:

kernel.shmall = 134217728
kernel.shmmax = 134217728

此文件通常在引导时被处理,但之后也可以显式调用 sysctl。

其他参数对任何应用来说尺寸都已足够。如果你想亲自查看,可以看 /usr/src/linux/include/asm-xxx/shmpara m.h和/usr/src/linux/include/linux/sem.h。

MacOS X

在 OS X 10.2 及更早版本中,编辑文件 /System/Library/StartupItems/SystemTuning/SystemTuning 并更改以下命令中的值:

sysctl -w kern.sysv.shmmax
sysctl -w kern.sysv.shmmin
sysctl -w kern.sysv.shmmni
sysctl -w kern.sysv.shmseg
sysctl -w kern.sysv.shmall

在 OS X 10.3 中,这些命令已被移到/etc/rc中,必须 在那里编辑。

SCO OpenServer

在默认配置中,每个段只允许 512 kB 共享内存,大约只够 -B 24 -N 12使用。要提高此设置,首先切换到目录 /etc/conf/cf.d。要显示SHMMAX的当前值, 运行

./configure -y SHMMAX

要为SHMMAX设置新值,运行

./configure SHMMAX=value

其中value是你要使用的新值(以字节计)。设置 SHMMAX之后,重建内核:

./link_unix

然后重启。

Solaris

至少在 2.6 版中,共享内存段的默认最大尺寸对 PostgreSQL来说太低。相关设置可以在 /etc/system中更改,例如:

set shmsys:shminfo_shmmax=0x2000000
set shmsys:shminfo_shmmin=1
set shmsys:shminfo_shmmni=256
set shmsys:shminfo_shmseg=256

set semsys:seminfo_semmap=256
set semsys:seminfo_semmni=512
set semsys:seminfo_semmns=512
set semsys:seminfo_semmsl=32

需要重启才能使更改生效。

关于 Solaris 下共享内存的信息,另见 http://sunsite.uakom.sk/sunworldonline/swol-09-1997/swol-09-insidesolaris.html。

UnixWare

在 UnixWare 7 上,默认配置中共享内存段的最大 尺寸是 512 kB。这大约够 -B 24 -N 12使用。要显示 SHMMAX的当前值,运行

/etc/conf/bin/idtune -g SHMMAX

它会显示当前值、默认值、最小值和最大值。要为 SHMMAX设置新值,运行

/etc/conf/bin/idtune SHMMAX value

其中value是你要使用的新值(以字节计)。设置 SHMMAX之后,重建内核:

/etc/conf/bin/idbuild -B

然后重启。

16.5.2. 资源限制

类 Unix 操作系统强制执行多种资源限制,它们可能干扰 PostgreSQL 服务器的运行。特别重要的是 每用户进程数、每进程打开文件数以及每个进程可用内存量的限制。这些 限制都各有“硬”限制和“软”限制。实际生效 的是软限制,但用户可以把它提高到硬限制为止。硬限制只能由 root 用户更改。系统调用setrlimit负责设置这些参数。 从命令行控制资源限制使用 shell 内建命令ulimit (Bourne shell)或limit(csh)。 在 BSD 衍生的系统上,文件/etc/login.conf控制 登录时设置的各种资源限制。细节参见操作系统文档。相关参数是 maxproc、openfiles和 datasize。例如:

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

(-cur是软限制。加-max后缀 可设置硬限制。)

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

  • 在 Linux 上, /proc/sys/fs/file-max决定内核支持的最大 打开文件数。可以通过向该文件写入不同的数字或在 /etc/sysctl.conf中加入赋值来更改它。每进程 的最大文件数上限在内核编译时固定;更多信息见 /usr/src/linux/Documentation/proc.txt。

PostgreSQL服务器每个连接使用一个进程, 因此除了系统其余部分所需的进程外,你应当为允许的连接数准备至少 同样多的进程。这通常不是问题,但如果在一台机器上运行多个服务器, 就可能变得紧张。

打开文件数的出厂默认限制通常被设置为“兼顾大家”的值, 允许多个用户共存于一台机器而不占用过多的系统资源。如果你在一台 机器上运行许多服务器,这可能正合你意,但在专用服务器上,你可能 希望提高此限制。

另一方面,有些系统允许单个进程打开大量文件;如果不止几个进程这样 做,系统范围的限制就很容易被超出。如果你发现这种情况发生,而又 不想更改系统范围的限制,可以设置PostgreSQL 的max_files_per_process配置参数来限制打开文件 的消耗。

16.5.3. Linux 内存过量分配

在 Linux 2.4 及更高版本中,默认的虚拟内存行为对 PostgreSQL来说不是最优的。由于内核实现 内存过量分配的方式,如果其他进程的内存需求导致系统虚拟内存耗尽, 内核可能终止PostgreSQL服务器(即 postmaster进程)。

如果发生这种情况,你会看到类似这样的内核消息(该去哪里找这种 消息请查阅你的系统文档和配置):

Out of Memory: Killed process 12345 (postmaster). 

这表明postmaster进程因内存压力而被终止。 虽然现有的数据库连接会继续正常工作,但不会接受新连接。要恢复, 需要重启PostgreSQL。

避免此问题的一种方法是把PostgreSQL 运行在这样一台机器上:你能确保其他进程不会把机器的内存耗尽。

在 Linux 2.6 及更高版本中,更好的解决方案是修改内核的行为,使其 不“过量分配”内存。这可以通过 sysctl 选择严格的过量分配 模式来完成:

sysctl -w vm.overcommit_memory=2

或者在/etc/sysctl.conf中加入等价的条目。你可能还想 修改相关的设置vm.overcommit_ratio。细节见内核文档文件 Documentation/vm/overcommit-accounting。

据报告,一些厂商的 Linux 2.4 内核带有 2.6 过量分配 sysctl 的早期 版本。然而,在没有相关代码的内核上把vm.overcommit_memory 设置为 2 会使情况变得更糟而不是更好。建议你在 2.4 安装上尝试此 操作之前,检查实际的内核源代码(见文件mm/mmap.c中的 函数vm_enough_memory)来验证你的副本支持什么。存在 overcommit-accounting文档文件并不能作为 该特性存在的证据。如有疑问,请咨询内核专家或你的内核供应商。

提交更正

译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。