一、环境:
操作系统:Windows 2003+SP2
数据库: Oracle9i
版本: 9.2.0.1.0
网络相关:IIS6
程序: WebService提供对移动设备对数据的操作
网页程序提供用户查看数据
二、现象:
10月8日,在服务器上新安装了一个服务程序WinServiceBswxwms.exe(其功能是将每日的生产数量整理成一定的格式,生成一个报表,即数据的提取与整理),但是一段时间后来发现,客户端的网页出现如下错误(Ora-00018)
到服务器本机用Enterprise Manager Console打开数据库,出现如下错误
Ora-00604 Error Occurred at recursive SQL Leavel 1
Ora-00018 Maximum number of sessions exceeded
查了一下网络上的资料,基本上都是说出现Ora-00018是因为Process的值设置过小(Oracel默认为150),导致实际的Session值会超过Oracle的设置值(Session的数量是Process*1.1+5),所以会出错,建议将Process的值往大了改。(Oracle默认的Process值为150)
查看当前系统中的Process
SQL> show parameter processes;
NAME TYPE VALUE
------------------------------------ ----------- -------
aq_tm_processes integer 1
db_writer_processes integer 1
job_queue_processes integer 10
log_archive_max_processes integer 2
processes integer 150
SQL> show parameter sessions;
NAME TYPE VALUE
------------------------------------ ----------- ------
java_max_sessionspace_size integer 0
java_soft_sessionspace_limit integer 0
license_max_sessions integer 0
license_sessions_warning integer 0
logmnr_max_persistent_sessions integer 1
mts_sessions integer 165
sessions integer 170
shared_server_sessions integer 165
于是将Process设置为500
SQL> alter system set processes=500 scope=spfile;
系统已更改。
重新启动数据库使改动生效。
SQL> shutdown immediate;
数据库已经关闭。
已经卸载数据库。
ORACLE 例程已经关闭。
SQL> startup
ORACLE 例程已经启动。
再次查看,确实改过来了。
SQL> show parameter processes;
NAME TYPE VALUE
------------------------------------ ----------- -------
aq_tm_processes integer 1
db_writer_processes integer 1
job_queue_processes integer 10
log_archive_max_processes integer 2
processes integer 500
SQL> show parameter sessions;
NAME TYPE VALUE
------------------------------------ ----------- ------
java_max_sessionspace_size integer 0
java_soft_sessionspace_limit integer 0
license_max_sessions integer 0
license_sessions_warning integer 0
logmnr_max_persistent_sessions integer 1
mts_sessions integer 550
sessions integer 555
shared_server_sessions integer 550
但是发现其改为500后,没有事了,可以安心回家睡觉了,没有想到,回家睡了不到4个小时,又被公司的人喊了回来说我们的网页怎么上不去了!现在可是凌晨3点啊!!!
回到公司一看果然仍然有报错,是Ora-00020 Maximum Number of processes(500) execeed!
(我的乖乖,设置为500还会Session还会超!!!但是当时是半夜,真正使用的最多不会超过10个人!)
意识到问题不是那么简单了!!!不可能会有这么多人同时用客户端什么的去连接数据库吧!
(我们公司总共才不过千把台电脑)
重新启动数据库后,发现Session数和无效Session数少的可怜。
SQL> select count(1) from v$session ';
COUNT(1)
----------
12
SQL> select count(1) from v$session where status = 'INACTIVE';
COUNT(1)
----------
6
但是过了3个小时。。。。。。
SQL> show user
USER ?S "SYS"
SQL> select count(*) from v$session;
COUNT(*)
----------
496
SQL> select count(1) from v$session where status = 'INACTIVE';
COUNT(1)
----------
486
好多的Session和好多的无效Session哦!!问题肯定出在这个无效Session上。
在Oracle的管理控制台点击看看,依次展开网络-->数据库-->服务名-->例程-->会话,在右面的无效Session双击看看到底是什么东西!!!
发现是WinServiceBswxwms.exe占用引起的!
原来是新安装的程序在作怪!问题找到了
三、分析
原来无效的Session都是由WinServiceBswxwms.exe这个程序引起的,回想在写程序时,没有考虑到数据库的连接与释放问题,因为这个程序是每1分钟执行一次,如果时间是早上的8点10分时,就将生产实绩表中的数据写入到另外一张报表中,而数据库连接的语句写在了循环外部,就导致不管现在是否8点10分,都需要连接一次数据库,然后判断是否现在是否8点10分,如果是则将数据写入,如果不是跳出。
而且连接了数据库没有释放,所以无效Session会有这么多。
四、解决方法:
这下好办了,改写程序,将这个程序中的数据库连接写在循环内部,这样的话,只有到8点10分,它才会去连接数据库,并且一执行完后就释放数据库连接。
五、
验证,又过了几个个小时,一切正常。。。。。
SQL> select count(*) from v$session;
COUNT(*)
----------
16
SQL> select count(1) from v$session where status = 'INACTIVE';
COUNT(1)
----------
5
六、总结:此次问题害得我有两个晚上没有睡好,都是从热乎乎的被窝里爬出来,赶到公司加班的……
1、一个问题往往没有那么简单,必须调查其起因。(第一次使用部门跟我说网页不能上的时候我以为是服务器哪里出错了,就打电话过去说等等,我把服务器重新启动一下啊!当时有用了,没有想到,没过多久,又出错了)
2、写程序时逻辑要写得明了。
3、最重要的是一个新程序不能直接放到服务器上,要经过一定时间的测试(调试没有问题不等于测试没有问题)