3.5. 管理内核资源 #
一个大型Postgres安装会很快耗尽各种操作系统资源限制。(在某些系统上,出厂默认值非常低,你甚至不需要真正“大型”的安装就会遇到问题。)如果你遇到过这类问题,请继续阅读。
3.5.1. 共享内存和信号量 #
共享内存和信号量统称为“System V IPC”(连同消息队列,但消息队列与 Postgres无关)。几乎所有现代操作系统都提供这些特性,但并非所有系统都默认启用了它们或将其设置得足够大,尤其是有 BSD 血统的系统。(对于 QNX 和 BeOS 移植,Postgres 为这些设施提供了自己的替代实现。)
完全缺少这些功能时,通常会在服务器启动时出现 Illegal system call 错误。在这种情况下,除了重新配置内核别无选择。没有它们,Postgres 无法工作。
当Postgres超出各种硬性 IPC 限制之一时,postmaster 会拒绝启动,并应留下带有指导性的错误消息,说明所遇到的问题以及应如何处理(另见第 3.3.1 节)。相关内核参数在不同系统上的命名基本一致,表 3.2给出了概览。不过,设置它们的方法却各不相同。下面给出一些平台上的建议。请注意,更改这些设置通常需要重启机器,甚至可能需要重新编译内核。
表 3.2. System V IPC 参数
| 名称 | 描述 | 合理的值 |
|---|---|---|
SHMMAX | 共享内存段的最大尺寸(字节) | 250 kB + 8192 * buffers,或无穷大 |
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 | 信号量的最大值 | >= 255(默认值常常是 32767,如非必要不要更改) |
最重要的共享内存参数是
SHMMAX,即一个共享内存段所能拥有的最大尺寸(以字节计)。如果 shmget 返回类似
Invalid argument 这样的错误消息,可能是超出了这个限制。所需共享内存段的尺寸随请求的共享缓冲区数量和允许的连接数量(-B/-N 选项)而变化,尽管前者的影响最大。(作为临时解决办法,你可以调低这些设置来消除失败。)粗略估计,你可以用缓冲区数量乘以块大小(默认
8192 kB)再加上充足的额外开销(至少半兆字节)来估算所需的段尺寸。你可能得到的任何错误消息都会包含失败分配请求的尺寸。
不太可能出问题的是共享内存段的最小尺寸(SHMMIN),对Postgres来说最多大约在 256 kB 上下(通常只是
1)。系统范围(SHMMNI)或每进程(SHMSEG)的最大共享内存段数目不会导致问题,除非你的系统把它们设成零。有些系统还对系统内共享内存的总量有限制;参见下面的平台特定说明。
Postgres为每个允许的连接(-N 选项)使用一个信号量,每 16 个组成一组。每组还包含第 17 个信号量,其中存放一个“魔数”,用来避免与其他应用程序使用的信号量集的冲突。系统中的信号量最大数量由SEMMNS设置,因此它必须至少等于连接设置再加上每 16 个允许连接一个的额外信号量(见表 3.2中的公式)。参数SEMMNI
决定系统中同时可以存在的信号量集的数量上限,因此它必须至少为
ceil(max_connections / 16)。降低允许的连接数是失败时的一种临时变通办法,这种失败通常表现为semget()
函数返回措辞令人困惑的“No space left on
device”。
在某些情况下,可能最终还需要增大SEMMAP,使其至少与
SEMMNS处于同一数量级。这个参数定义信号量资源映射的大小,其中每个连续的可用信号量块都需要占用一项。每当一个信号量集合被释放时,它要么会并入与该释放块相邻的现有项,要么会登记为一个新的映射项。如果映射已满,被释放的信号量就会丢失(直到重启)。因此,信号量空间的碎片化随时间推移可能导致可用信号量少于应有数量。
SEMMSL参数决定一个信号量集中可以包含多少个信号量,对于Postgres,它必须至少为 17。
与“信号量撤销”有关的其他各种设置,如SEMMNU
和SEMUME,对Postgres无关紧要。
- BSD/OS
共享内存. 默认只支持 4 MB 共享内存。请记住,共享内存是不可换页的,它被锁定在 RAM 中。要增加 postmaster 支持的共享缓冲区数量,可以在内核 config 文件中加入下面的内容。
SHMALL值 1024 表示 4 MB 共享内存。以下设置把最大共享内存区域增加到 32 MB:options "SHMALL=8192" options "SHMMAX=\(SHMALL*PAGE_SIZE\)"
对于运行 4.1 或更高版本的用户,只需做上述更改、重新编译内核并重启。对于运行更早版本的用户,可用bpatch在当前内核中找到
sysptsize值。该值是在引导时动态计算的。$
bpatch -r sysptsize0x9 = 9然后,在内核 config 文件中把
SYSPTSIZE加为硬编码值。把你用bpatch找到的值增大。每想要 4 MB 额外共享内存就加 1。options "SYSPTSIZE=16"
sysptsize无法通过 sysctl 更改。Semaphores. 你可能需要增加信号量的数量。默认情况下,Postgres分配 34 个信号量,这超过了系统默认总数 60 的一半。
在内核 config 文件中设置你想要的值,例如:
options "SEMMNI=40" options "SEMMNS=240" options "SEMUME=40" options "SEMMNU=120"
- FreeBSD
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
- HP-UX
默认设置通常足以满足普通安装的需求。在 HP-UX 10 上,
SEMMNS的出厂默认值为 128,对较大的数据库站点来说可能过低。可以在 System Administration Manager(SAM)的 → 中设置 IPC 参数。完成后选择 。
- 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/shmparam.h/usr/src/linux/include/linux/sem.h。- 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 版中,为共享内存段设置的默认最大尺寸对 Postgres来说太低。相关设置可以在
/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://www.sunworld.com/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
然后重启。
3.5.2. 资源限制
类 Unix 操作系统强制执行多种资源限制,它们可能干扰
Postgres 服务器的运行。尤其重要的是每用户进程数、每进程打开文件数以及每个进程可用内存量的限制。这些限制都各有“硬”限制和“软”限制。实际生效的是软限制,但用户可以把它提高到硬限制为止。硬限制只能由 root
用户更改。系统调用setrlimit负责设置这些参数。从命令行控制资源限制使用 shell 内建命令ulimit(Bourne shell)或limit(csh)。在 BSD 衍生的系统上,文件/etc/login.conf控制登录时各种资源限制所设置的值。细节参见
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。
Postgres服务器每个连接使用一个进程,因此除了系统其余部分所需的进程外,你应当为允许的连接数准备至少同样多的进程。这通常不是问题,但如果在一台机器上运行多个服务器,就可能变得紧张。
打开文件数的出厂默认限制通常被设置为“兼顾大家”的值,允许多个用户共存于一台机器而不占用过多的系统资源。如果你在一台机器上运行许多服务器,这可能正合你意,但在专用服务器上,你可能希望提高此限制。