问题背景:
用户一套之前可以正常启动的数据库,在一次重启之后,数据库无法正常启动,报信号量资源不足问题。
ORA-27154: post/wait create failed
ORA-27300: OS system dependent operation:semget failed with status: 28
ORA-27301: OS failure message: No space left on device
ORA-27302: failure occurred at: sskgpbitsper
信号量介绍:
在问题分析开始之前,我们先了解一下Linux服务器的IPC和信号量,IPC是指进程之间通信交换数据和信息的一种机制,不同进程之间通过IPC机制实现数据传输、同步和协作,而信号量是IPC实现机制中的一种方式,其他IPC方式还包括消息队列、共享内存和管道,信号量在进程间通信IPC机制中主要充当操作锁的方式,用于控制进程之间对同一资源的申请访问,避免多个进程出现同一时间访问同一资源的问题。在操作系统上面,我们可以通过ipc命令查看信号量的分配使用情况。
查看每个信号量ipcs -s
------ Semaphore Arrays --------
key semid owner perms nsems
0x869d3e0c 229378 grid 640 182
0x869d3e0d 262147 grid 640 182
0x869d3e0e 294916 grid 640 182
0xd02c18d8 622600 oracle 640 250
0xd02c18d9 655369 oracle 640 250
0xd02c18da 688138 oracle 640 250
0xd02c18db 720907 oracle 640 250
0xd02c18dc 753676 oracle 640 250
0xd02c18dd 786445 oracle 640 250
0xd02c18de 819214 oracle 640 250
0xd02c18df 851983 oracle 640 250
0xd02c18e0 884752 oracle 640 250
查看信号量的总使用情况ipcs -su
------ Semaphore Status --------
used arrays = 14
allocated semaphores = 2798
查看信号量的操作/变化时间ipcs -st
------ Semaphore Operation/Change Times --------
semid owner last-op last-changed
229378 grid Tue Mar 26 09:32:14 2024 Tue Mar 26 09:32:14 2024
262147 grid Not set Tue Mar 26 09:30:33 2024
294916 grid Tue Mar 26 09:30:39 2024 Tue Mar 26 09:30:39 2024
622600 oracle Tue Mar 26 10:17:59 2024 Tue Mar 26 10:17:59 2024
655369 oracle Not set Tue Mar 26 09:31:18 2024
688138 oracle Not set Tue Mar 26 09:31:18 2024
720907 oracle Not set Tue Mar 26 09:31:18 2024
753676 oracle Not set Tue Mar 26 09:31:18 2024
786445 oracle Not set Tue Mar 26 09:31:18 2024
819214 oracle Not set Tue Mar 26 09:31:18 2024
851983 oracle Not set Tue Mar 26 09:31:18 2024
884752 oracle Tue Mar 26 09:31:29 2024 Tue Mar 26 09:31:29 2024
查看信号量的配置情况ipcs -sl
------ Semaphore Limits --------
max number of arrays = 128
max semaphores per array = 250
max semaphores system wide = 32000
max ops per semop call = 100
semaphore max value = 32767
信号量的参数由sysctl.conf的内核参数kernel.sem:Semmsl Semmns Semopm Semmni所配置,需要配置以下四个参数值。
Semmsl:This is the maximum number of semaphores that can be allocated in a semaphore set. (semget(), EINVAL),定义信号集中的信号量的分配最大数量。
Semmns:This is a system-wide limit on the number of semaphores in all semaphore sets. The number of semaphores on the system is also limited by SEMMNI and SEMMSL; in fact, the default value for SEMMNS is the product of the defaults for these two limits. (semget(), ENOSPC),定义操作系统总的信号量数目,等于Semmsl* Semmni,Linux最大为32767。
Semopm:This is the maximum number of operations per semop() call. (semop(), E2BIG),定义semop函数可以操作信号的最大数量,semop的操作对象为信号集。
Semmni:This is a system-wide limit on the number of semaphore identifiers (in other words, semaphore sets) that can be created. (semget(), ENOSPC),定义操作系统的信号标识符也就是信号集的最大数量,在信号量的使用中,通常定义和操作都是先一个信号集为单位,再操作信号集里面的信号。
对于Oracle数据库服务器,Oracle官方的建议kernel.sem配置最小值为250 32000 100 128,这个配置可以满足绝大部分的生产环境,正常一个实例差不多分配10个左右信号集和2000左右的信号量。
问题分析:
重新回到报错的问题,检查当前启动失败数据库的操作系统信号量配置kernel.sem,可以看到当前配置为Oracle官方建议的kernel.sem配置最小值250 32000 100 128,服务器上只跑了一个数据库实例,配置应该是可以满足的使用。
使用ipcs -su命令查看当前信号量的使用情况,可以看到信号集的使用量为128,信号的使用为6671,可以看到是因为信号集的分配已经达到kernel.sem参数Semmni的上限,所以数据库启动的时候会报ORA-27300,ORA-27301信号量不足的错误。
检查信号集的使用情况,通过ipcs -s命令查看当前的信号集分配,可以看到Oracle用户使用到的信号集其实只有9个,其他大部分都是被zabbix监控工具用户所分配使用,这里zabbix工具使用了这么多的信号量,而且key都是0x00000000,看起来不太正常,后续让用户的监控管理员去进一步去排查zabbix用户信号量使用的问题。
问题解决:
1 可以通过修改操作系统kernel.sem的信号集Semmni参数配置,增加操作系统的信号的数量,调大信号集到228,这里Semmns没有设置为Semmsl* Semmni,是因为操作系统Semmns最大值为32767。
--修改sysctl.conf配置
vi /etc/sysctl.conf
kernel.sem = 250 32767 100 228
--生效配置
sysctl -p
2 通过ipcrm -S删除信号集,释放信号集,批量删除zabbix用户下的key。
#!/bin/bash
for i in `ipcs -s |grep zabbix|awk '{ print $1 }'`
do
ipcrm -S $i
done
Tip:欢迎关注公众号:勇敢牛牛的笔记,超100+的原创内容,每周不定期更新数据库技术文章。