一客户机房新装的UPS不太稳定,好几次意外断电,第3次意外断电之后问题终于来了,
数据库起不来了……
数据库的硬件环境是一台IBM DS5020存储,2台IBM X3850 X5
软件环境是Linux与Oracle 10g RAC
数据库2个节点的asm都能正常启动,但数据库实例启动到mount状态后就停下没有反应了,
等很久也不能前进到open状态。
节点1上的alert日志有如下错误信息:
ORA-1013 signalled during: ALTER DATABASE OPEN
…………
ORA-1089 signalled during: alter database open
节点2上的alert日志有如下错误信息:
Thu Dec 29 15:32:46 2011
Errors in file /opt/oracle/admin/racdb/bdump/racdb2_p015_11496.trc:
ORA-27090: Message 27090 not found; product=RDBMS; facility=ORA
Linux-x86_64 Error: 4: Interrupted system call
Additional information: 3
Additional information: 128
Additional information: 65536
进一步查看/opt/oracle/admin/racdb/bdump/racdb2_p015_11496.trc,有如下信息:
ORA-27090: Message 27090 not found; product=RDBMS; facility=ORA
Linux-x86_64 Error: 4: Interrupted system call
Additional information: 3
Additional information: 128
Additional information: 65536
WARNING:io_submit failed due to kernel limitations MAXAIO for process=0 pending aio=0
WARNING:asynch I/O kernel limits is set at AIO-MAX-NR=65536 AIO-NR=65508
WARNING:Oracle process running out of OS kernel I/O resources (1)
WARNING:Oracle process running out of OS kernel I/O resources (1)
WARNING:Oracle process running out of OS kernel I/O resources (1)
WARNING:Oracle process running out of OS kernel I/O resources (1)
上面日志中提示了linux的核心参数设置有问题:AIO-MAX-NR=65536
我们知道,Linux的核心参数AIO-MAX-NR是与异步IO相关的,对于异步IO的简单解释如下:
在一个程序中如果涉及到磁盘的IO操作时,有两种情况
1. 程序等待IO操作完成,CPU再接下来处理程序的其他部分(等待IO的时间段内,CPU处于Idle Waiting状态)。
2. 程序不等待IO操作完成,允许CPU处理接下来的其他任务(或者理解为允许CPU处理接下来的不依赖于IO完成的任务)。
显然,第一种情况,CPU的资源白白的浪费了,也就是同步IO。第二种情况更有利于CPU的充分利用,这就是异步IO(asynchronous IO)。
查看操作系统的异步IO相关核心参数:
[root@db01 ~]# sysctl -a| grep aio
fs.aio-max-nr = 65536
fs.aio-nr = 0
我们知道aio-nr是所有当前活动的异步IO进程上下文的总和,其值最多不能超过aio-max-nr的设定值。并且数据库是在机房意外断电的情况下突然关闭的,关闭的一瞬间有大量的事务正在运行,所以重新启动的时候必然有大量的回滚与已提交但没有写入到数据文件的数据要开始写入,这时候的IO量是非常大的,由于启用了异步IO,此时大量的上下文切换达到了操作系统设定的最大值,于是oracle就停止响应了。查询metalink了解到oracle已证实这是一个BUG,官方建议fs.aio-max-nr的值设置为1M或以上可以解决此问题。
这里我将调整核心参数fs.aio-max-nr的值为3145728,即3M。
[root@db01 ~]# echo "fs.aio-max-nr = 3145728" >> /etc/sysctl.conf
[root@db01 ~]# sysctl -p
net.ipv4.ip_forward = 0
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.default.accept_source_route = 0
kernel.sysrq = 0
kernel.core_uses_pid = 1
net.core.rmem_default = 262144
net.core.rmem_max = 262144
net.core.wmem_default = 262144
net.core.wmem_max = 262144
net.ipv4.tcp_sack = 0
net.ipv4.tcp_timestamps = 0
net.ipv4.ip_local_port_range = 1024 65000
kernel.sem = 500 64000 100 128
kernel.shmmax = 17179869184
kernel.shmall = 4194304
fs.aio-max-nr = 3145728
两台服务器的核心参数都做了上面的修改之后,数据库启动成功!