[20260508]关于内核参数kernel.sem.txt

[20260508]关于内核参数kernel.sem.txt

--//前几天测试使用oracle数据库,ipcs -m输出shmid的生成规律,顺便再看看ipcs -s输出semid的生成规律。
--//在测试前,先了解内核参数kernel.sem属性的设置:

kernel.sem = SEMMSL SEMMNS SEMOPM SEMMNI

where

SEMMSL  max semaphores per array                      每组信号量
SEMMNS  max semaphores system wide ,SEMMSL*SEMMNI     可用信号量的总数
SEMOPM  max ops per semop call, SEMOPM=SEMMSL?       每个信号量呼叫可以执行的操作数。
SEMMNI  max number of arrays                          信号集的最大数量

--//我的测试环境:
# cat /proc/sys/kernel/sem
250     32000   250     128

其4个值的含义分别如下:
① 250表示SEMMSL,设置每个信号灯组中信号灯最大数量,推荐的最小值是250。对于系统中存在大量并发连接的系统,推荐将这个值设
   置为PROCESSES初始化参数加10。
--// 实际上对于linux 设置为PROCESSES初始化参数加4就可以了。
② 32000表示SEMMNS,设置系统中信号灯的最大数量。操作系统在分配信号灯时不会超过LEAST(SEMMNS,SEMMSL*SEMMNI)。事实上,如果
   SEMMNS的值超过了SEMMSL*SEMMNI是非法的,因此推荐SEMMNS的值就设置为SEMMSL*SEMMNI。Oracle推荐SEMMNS的设置不小于32000。
--//SEMMSL*SEMMNI=250*128 = 32000
③ 100表示SEMOPM,设置每次系统调用可以同时执行的最大信号灯操作的数量。由于一个信号灯组最多拥有SEMMSL个信号灯,因此有推荐
   将SEMOPM设置为SEMMSL的值。Oracle验证的10.2和11.1的SEMOPM的配置为100。
--//我个人习惯配置等于SEMMSL。
④ 128表示SEMMNI,设置系统中信号灯组的最大数量。

--//按照前面的测试shmid的情况,semid值应该有一个基数B以及Semaphores array的数量相关,先将semid的测试放一放。

--//看来以前的笔记,当时的总结如下:

--//Semaphore Arrays的nsems(参考ipcs -s的输出)按照如下计算:
--//processes 小于等于SEMMSL ,nsem=processes+4.
--//(processes)/N,N=2的幂(2,4,8,16,32....).,再使用floor取整,小于等于SEMMSL,nsems = floor((processes)/N ).
--//Semaphore Arrays数量的算法应该是 ceil(processes/(nsems-4)) ,结果向上取整。

--//注意:21c似乎改变算法,使用processes除,而不是processes+4,以上已经做了更正.
--//补充:11g缺省使用processes+4除.

--//另外我看了链接http://blog.itpub.net/267265/viewspace-2664807/=>[20191119]探究ipcs命令输出2.txt
--//zergduan的评论 2020-05-19 19:23:54
你的测试是正确的,但是也是有局限的,你看到4个信号量被保留,不做分配,是因为你在AMD/Intel x86架构的服务器上测试;这个架构
保留值就是4,其它架构保留值不一样,但是一般不会超过10,所以网上经常说第一个值设置为processes+10; 其实这是为了让一个实例
的只使用一个信号量集,这对于processes很小的实例是可以的,但是对于processes很大的实例,就不应该这样设置了。
--//也就是linux 是+4,其它os可能是processes+10.

--//使用测试环境说明:
1.环境:
SYS@book> @ ver2
==============================
PORT_STRING                   : x86_64/Linux 2.4.xx
VERSION                       : 21.0.0.0.0
BANNER                        : Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production
BANNER_FULL                   : Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production
Version 21.3.0.0.0
BANNER_LEGACY                 : Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production
CON_ID                        : 0
PL/SQL procedure successfully completed.

SYS@book> @ hidez ^processes
SYS@book> @ pr
==============================
NUM                           : 52
N_HEX                         :    34
CON_ID                        : 0
NAME                          : processes
DESCRIPTION                   : user processes
DEFAULT_VALUE                 : FALSE
SESSION_VALUE                 : 246
SYSTEM_VALUE                  : 246
ISSES_MODIFIABLE              : FALSE
ISSYS_MODIFIABLE              : IMMEDIATE
PL/SQL procedure successfully completed.

2.测试:
$ ipcs -s
------ Semaphore Arrays --------
key        semid      owner      perms      nsems
0x5507207c 98304      oracle     600        250

--//顺便记录主机开始第1次启动数据库的semid=98304
--//98304: 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3,共计15个2,也就是2^15*3.

--//processes+4 = 246+4 = 250,这样正好等于SEMMSL,这样使用1个信号集。
--//注:测试环境,故意为之.

$ ipcs -s -i 98304 | awk '$5i!=0 {print $0}'

Semaphore Array semid=98304
uid=54321        gid=54321       cuid=54321      cgid=54321
mode=0600, access_perms=0600
nsems = 250
otime = Fri May  8 15:26:08 2026
ctime = Fri May  8 15:26:08 2026
semnum     value      ncount     zcount     pid
0          0          0          0          3428
1          17405      0          0          3428
2          25823      0          0          3428
3          32761      0          0          3428
6          0          1          0          3437
7          0          1          0          3441
8          0          1          0          3445
10         0          1          0          3455
11         0          1          0          3459
......
77         0          0          0          3717
78         0          0          0          3719
79         0          0          0          3721
80         0          0          0          3723
81         0          0          0          3725
82         0          0          0          3727
83         0          0          0          3729
84         0          1          0          3731
85         0          0          0          3733
86         0          0          0          3735
87         0          0          0          3737
88         0          0          0          3739
249        0          0          0          3428
--//semnum 从0-249,也就是总数250.注意看最后1列,前面4个(semnum=0~3)pid=3428,最后1个(semnum=249),pid=3428.也就是有5个是,也
--//就是实际容纳进程的数量是processes-1=245.
--//我以前的建议如果processes不大,尽量在1个Semaphore Arrays.好像多个Semaphore Arrays也看不出什么性能问题.

3.测试:
--//如果修改内核参数如下:
# sysctl -w "kernel.sem=30 32000 30 128"
kernel.sem = 30 32000 30 128

--//计算过程如下:
--//processes+4 = 246+4 = 250。
--// 246/2
--//246/2^2
--//246/2^3  = 30.75 ,floor(30.75)=30,小于等于SEMMSL=30, nsems = floor((processes+4)/2^N ) =30.

--//接着看看Semaphore Arrays数量,计算公式  ceil(processes/(nsems-4)) ,结果向上取整。
--//这是因为每个信号集的前4个不可用,被启动进程占据.
--//250/(30-4) = 9.61, ceil(9.51) = 10.

--//验证是否正确,重启数据库:

$ ipcs -s
------ Semaphore Arrays --------
key        semid      owner      perms      nsems
0x5507207c 819200     oracle     600        30
0x5507207d 851969     oracle     600        30
0x5507207e 884738     oracle     600        30
0x5507207f 917507     oracle     600        30
0x55072080 950276     oracle     600        30
0x55072081 983045     oracle     600        30
0x55072082 1015814    oracle     600        30
0x55072083 1048583    oracle     600        30
0x55072084 1081352    oracle     600        30
0x55072085 1114121    oracle     600        30

$ ipcs -s | grep -c 0x
10
--//Semaphore Arrays数量=10.
--//看看semid=1114121

$ ipcs -s -i 1114121 | awk '$5!=0{print $0}'

Semaphore Array semid=1114121
uid=54321        gid=54321       cuid=54321      cgid=54321
mode=0600, access_perms=0600
nsems = 30
otime = Fri May  8 15:49:15 2026
ctime = Fri May  8 15:49:15 2026
semnum     value      ncount     zcount     pid
0          0          0          0          4587
1          17405      0          0          4587
2          25823      0          0          4587
3          32761      0          0          4587
15         0          0          0          4587
--//semnum=15,pid=4587,我的理解表示结束.前4个pid=4587不可用.前面每个信号集的前4个pid=4587.
--// 9*(30-4)+15-4 = 245.

--//顺便看看semid的变化:
# ipcs -s | awk '/[0=9]/{print $2}'| awk 'NR==1{printf "0x%08x %d\n",$1,$1;a=$1} NR>1{printf "0x%08x %d %d\n", $1,$1,$1-a;a=$1}'
0x000c8000 819200
0x000d0001 851969 32769
0x000d8002 884738 32769
0x000e0003 917507 32769
0x000e8004 950276 32769
0x000f0005 983045 32769
0x000f8006 1015814 32769
0x00100007 1048583 32769
0x00108008 1081352 32769
0x00110009 1114121 32769
--//与前面shmid的测试类似,呈等差数量,相差32769 = 0x8001.
--//819200: 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 5 5 = 2^15*25,注中间已经重启数据库多次.

--//实际上已经可以大致猜测semid的计算与shmid非常类似.另外写一篇说明.

请使用浏览器的分享功能分享到微信等