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