无论在Oracle还是DB2,大家在安装数据库之前,都需要对操作系统OS级别的信号量进行设置。尤其是Oracle,如果按默认设置不做更改,那么在precheck时,并不被通过。
其实PostgreSQL数据库中,也是一样,信号量对数据库系统尤为关健。因为数据库内部很多锁的实现以及进程间IPC(Inter-Process Communication)通信交互,都需要信号量。
这有点类似于,我们在公路上,需要交通信号灯一样,保证车辆安全有序通行。
以下是我摘了linux内核中,对于几个我们OS中经常用到的,跟信号量配置有关的参数的描述以及用途:
/*
* SEMMNI, SEMMSL and SEMMNS are default values which can be
* modified by sysctl.
* The values has been chosen to be larger than necessary for any
* known configuration.
*
* SEMOPM should not be increased beyond 1000, otherwise there is the
* risk that semop()/semtimedop() fails due to kernel memory fragmentation when
* allocating the sop array.
*/
#define SEMMNI 32000 /* <= IPCMNI max # of semaphore identifiers */
#define SEMMSL 32000 /* <= INT_MAX max num of semaphores per id */
#define SEMMNS (SEMMNI*SEMMSL) /* <= INT_MAX max # of semaphores in system */
#define SEMOPM 500 /* <= 1 000 max num of ops per semop call */
#define SEMVMX 32767 /* <= 32767 semaphore maximum value */
#define SEMAEM SEMVMX /* adjust on exit max value */
/* semop system calls takes an array of these. */
struct sembuf {
unsigned short sem_num; /* semaphore index in array */
short sem_op; /* semaphore operation */
short sem_flg; /* operation flags */
};
SEMMNI:这个是指系统中最大的semaphore set,也就是信号量集。
SEMMSL:指一个信号集中,能够拥有的最大信号量。
SEMMNS:是指整个系统级别,最大信号量。这个是前面两个参数的乘积:SEMMNI*SEMMSL=SEMMNS。
SEMOPM:在一个semop call中,每个信号量所允许的最大操作数。最大值为1000。
SEMVMX:每个信号量的最大值。semaphore分为Couting semaphore和Binary semaphore。Binary semaphore只有两种值,“0”和“1”;而这里应该是指Counting semaphore所能设置的最大值。
结构体sembuf封装了对semaphore的操作。
从“sysctl –a | grep sem”或者“cat /proc/sys/kernel/sem”中,我们通常可以提到当前系统中的值:
第一个值是SEMMSL,第二值是SEMMNS,第三个值是SEMOPM,第四个值是SEMMNI。32000=250*128。
通常对于数据库系统来讲,这几个默认值是不够的。一般Oracle或者DB2都有参数值或者建议值。我们只需要用sysctl命令设置成建议值就可以了。
另外,顺便也提一下几个跟内存相关的参数:
/*
* SHMMNI, SHMMAX and SHMALL are default upper limits which can be
* modified by sysctl. The SHMMAX and SHMALL values have been chosen to
* be as large possible without facilitating scenarios where userspace
* causes overflows when adjusting the limits via operations of the form
* "retrieve current limit; add X; update limit". It is therefore not
* advised to make SHMMAX and SHMALL any larger. These limits are
* suitable for both 32 and 64-bit systems.
*/
#define SHMMIN 1 /* min shared seg size (bytes) */
#define SHMMNI 4096 /* max num of segs system wide */
#define SHMMAX (ULONG_MAX - (1UL << 24)) /* max shared seg size (bytes) */
#define SHMALL (ULONG_MAX - (1UL << 24)) /* max shm system wide (pages) */
#define SHMSEG SHMMNI /* max shared segs per process */
SHMMNI:共享内存段最大段数
SHMMAX:单个share segment的最大值,以bytes计数。
SHMALL:共享内存最大值,以page计数。一般一个page,4K
得到当前系统中的值:
Oracle的SGA如果需要比较大的一个值,通常需要设置SHMMAX,能够容纳SGA segment。