错误信息:

pg_ctl[2442]: FATAL:  could not create semaphores: No space left on device
pg_ctl[2442]: DETAIL:  Failed system call was semget(5432129, 17, 03600).
pg_ctl[2442]: HINT:  This error does *not* mean that you have run out of disk space...

问题说明:

根据官方文档:https://www.postgresql.org/docs/9.2/static/kernel-resources.html的描述

PostgreSQL uses one semaphore per allowed connection (max_connections) and allowed autovacuum worker process (autovacuum_max_workers), in sets of 16. Each such set will also contain a 17th semaphore which contains a "magic number", to detect collision with semaphore sets used by other applications. The maximum number of semaphores in the system is set by SEMMNS, which consequently must be at least as high as max_connections plus autovacuum_max_workers, plus one extra for each 16 allowed connections plus workers (see the formula in Table 17-1). The parameter SEMMNI determines the limit on the number of semaphore sets that can exist on the system at one time. Hence this parameter must be at least ceil((max_connections + autovacuum_max_workers + 5) / 16). Lowering the number of allowed connections is a temporary workaround for failures, which are usually confusingly worded "No space left on device", from the function semget.

在linux系统环境下,PostgreSQL中的每个connection和autovacuum worker process都需要消耗一个信号量。
系统默认17个信号量为一个集合(由SEMMSL决定),其中包含16个普通信号量和一个"magic number"信号量(用来检测和其它应用使用的信号量集合的冲突)。

系统中信号量的最大数量显示为SEMMNS,它满足:SEMMNS = SEMMNI * SEMMSL

  • SEMMNI:信号量集合的最大数量(系统默认128)
  • SEMMSL:每个信号量集合包含的信号量数目(对于PostgreSQL而言应该至少是 17)

PostgreSQL启动的时候需要消耗的信号量标识符总量可以简单认为是:max_connections + autovacuum_max_workers。
当然其他应用程序也会消耗信号量资源。
PostgreSQL启动过程中如果信号量总数不够使用,就会报"No space left on device"。

查看系统信号量方法:

$ ipcs --limits

------ Messages Limits --------
max queues system wide = 15644
max size of message (bytes) = 8192
default max size of queue (bytes) = 16384

------ Shared Memory Limits --------
max number of segments = 4096
max seg size (kbytes) = 4194303
max total shared memory (kbytes) = 1073741824
min seg size (bytes) = 1

------ Semaphore Limits --------
max number of arrays = 128
max semaphores per array = 250
max semaphores system wide = 32000
max ops per semop call = 32
semaphore max value = 32767

或者

$ sysctl -a | grep sem
kernel.sem = 250    32000    32    128

SEMMSL:250
SEMMNS:32000 (SEMMSL * SEMMNI)
SEMOPM:32
SEMMNI:128

解决方法:

1、减少max_connections(修改postgresql.conf配置文件)
2、增大系统信号量总数
方法:在/etc/sysctl.conf中修改或追加下面一行内容:

kernel.sem = 250 50000 32 200

此处修改为:
SEMMSL:250
SEMMNS:50000 (SEMMSL * SEMMNI)
SEMMNI:200

修改完后执行

$ sysctl -p