pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。
一个大型PostgreSQL安装会很快耗尽各种操作系统资源限制。(在某些系统上,出厂默认值非常低,你甚至不需要真正“大型”的安装就会遇到问题。)如果你遇到过这类问题,请继续阅读。
共享内存和信号量合称“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选项)而变化,尽管前者影响最大。(作为临时解决方案,你可以降低这些设置来消除故障。)作为粗略的近似,你可以按照表 16.2中的建议估计所需的段尺寸。你可能得到的任何错误消息都会包含失败分配请求的尺寸。
有些系统还对系统中共享内存的总量(SHMALL)有限制。请确保它足够容纳PostgreSQL以及使用共享内存段的其他任何应用程序。(注意:在许多系统上SHMALL以页而不是字节计量。)
较不容易引起问题的是共享内存段的最小尺寸(SHMMIN),对PostgreSQL来说它至多需要大约 256 kB(通常就是 1)。系统范围内(SHMMNI)或每进程(SHMSEG)的最大段数不太可能引起问题,除非你的系统把它们设置成了零。
PostgreSQL为每个允许的连接(-N选项)使用一个信号量,每 16 个组成一组。每个这样的集合还包含第 17 个信号量,其中存放一个“魔数”,用于检测与其他应用程序所用信号量集合的冲突。系统中信号量的最大数量由SEMMNS设置,因此它必须至少与max_connections一样高,并且每 16 个允许的连接额外多一个(见表 16.2中的公式)。参数SEMMNI决定系统中同一时刻可以存在的信号量集数量的上限。因此该参数必须至少为ceil(max_connections / 16)。降低允许的连接数是对失败的临时变通办法,这类失败通常表现为措辞令人困惑的No space left on device,来自函数semget。
在某些情况下,可能还需要把SEMMAP增大到至少与SEMMNS相当的量级。这个参数定义信号量资源映射的大小,其中每一段连续的可用信号量都需要一个条目。当一个信号量集被释放时,它要么被加入与被释放块相邻的现有条目,要么被登记到一个新的映射条目下。如果映射已满,被释放的信号量就会丢失(直到重新启动)。信号量空间碎片化可能随时间导致可用信号量比应有的少。
决定一个集合中可以有多少信号量的SEMMSL参数,对PostgreSQL来说必须至少是 17。
与“信号量撤销”相关的其他设置(如SEMMNU和SEMUME)对PostgreSQL无关紧要。
共享内存. 默认只支持 4 MB 共享内存。请记住共享内存是不可换页的;它被锁定在 RAM 中。要增加系统支持的共享内存量,可以在内核配置文件中加入类似下面的内容:
options "SHMALL=8192" options "SHMMAX=\(SHMALL*PAGE_SIZE\)"
SHMALL以 4KB 页计量,因此值 1024 表示 4 MB 共享内存。因此上面的设置把最大共享内存区域增加到 32 MB。对于运行 4.3 或更高版本的用户,可能还需要把KERNEL_VIRTUAL_MB增大到默认值248之上。完成所有更改后,重新编译内核并重新启动。
对于运行 4.0 及更早版本的用户,使用bpatch找出当前内核中的sysptsize值。它是在引导时动态计算的。
$bpatch -r sysptsize0x9 = 9
接下来,在内核配置文件中加入SYSPTSIZE作为硬编码值。把你用bpatch找到的值增大。每需要额外的 4 MB 共享内存就加 1。
options "SYSPTSIZE=16"
sysptsize不能用sysctl更改。
信号量. 你可能还想增加信号量的数量;系统默认总量 60 只允许大约 50 个PostgreSQL连接。在内核配置文件中设置你想要的值,例如:
options "SEMMNI=40" options "SEMMNS=240"
编译内核时需要启用选项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
(在OpenBSD上关键字实际上写作单数形式option。)
你可能还想配置内核把共享内存锁定在 RAM 中,防止它被换出到交换空间。使用sysctl设置kern.ipc.shm_use_phys。
默认设置通常足以满足普通安装。在HP-UX 10 上,SEMMNS的出厂默认值是 128,对于较大的数据库站点可能太低。
IPC参数可以在System Administration Manager(SAM)中的 → 下设置。完成后点击。
在 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/shmparam.h/usr/src/linux/include/linux/sem.h。
在 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并且必须在其中编辑。你需要重新启动才能使更改生效。注意/etc/rc通常会被 OS X 更新(例如从 10.3.6 到 10.3.7)覆盖,因此应当预料到每次更新之后都需要重新编辑。
在这个平台上SHMALL以 4KB 页计量。
在默认配置中,每个段只允许 512 kB 共享内存,大约够用-B 24 -N 12。要增大这个设置,首先切换到目录/etc/conf/cf.d。要显示SHMMAX的当前值,运行
./configure -y SHMMAX
要为SHMMAX设置新值,运行
./configure SHMMAX=value
其中value是你要使用的新值(以字节计)。设置好SHMMAX后,重建内核:
./link_unix
然后重新启动。
至少在 5.1 版中,不需要对SHMMAX这类参数做任何特殊配置,因为它似乎被配置为允许所有内存都用作共享内存。这是其他数据库(如DB/2)常用的配置方式。
不过,可能需要修改/etc/security/limits中的全局ulimit信息,因为文件尺寸(fsize)和文件数量(nofiles)的默认硬限制可能太低。
至少在 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 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
然后重新启动。
类 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配置参数来限制其打开文件的消耗。
在 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 参数的早期实现。但是,在没有相关代码的 2.4 内核上将 vm.overcommit_memory 设为 2,会使情况更糟,而非更好。建议在 2.4 安装上尝试之前,检查实际内核源码(参见文件 mm/mmap.c 中的函数 vm_enough_memory),确认内核支持的功能。存在 overcommit-accounting 文档文件,不能作为该功能已存在的证据。如有任何疑问,请咨询内核专家或内核供应商。
译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。