前言
编者注,本文的知识点较多,请补充足够正能量后阅读,看完会让你质疑你的DBA生涯,作者的水平代表着国内Oracle TroubleShooting最高水平。
很早就想把ORA-1000的问题,总结成一个话题。机缘巧合,最近恰好遇上几个此类问题,特分享分析过程出来供大家参考。
首先,ORA-1000报错是什么意思呢?我们来看看官方的解释:
非常简单,单个进程打开的游标数超过了最大值,也就是超过了数据库设置的open_cursos参数的值;面对这样的情况,不同的DBA会有不同的解决方案:调整open_cursors参数?还是直接把问题抛给开发人员?
今天老猫就来给大家分享一个处理ORA-1000的经典案例,看看大家的处理方式和我们的处理方式有什么不一样?在处理过程中老猫又用到了什么不一样的处理技巧?处理完能收获什么样的心得体会?
2
来活啦
客户来电求助,系统周期性地报ORA-1000的错误,之前客户已经多次调整open_cursors参数,目前已经调整到了2000了,难道还是接着一直往上调?open_cursors是针对一个单个进程打开cursor数的限制,对于一般应用来说,如果能及时关闭cursor,2000个已经足够使用,那么这里是客户没有正确关闭游标还是其本身就需要同时打开大量游标抑或是其他原因呢,这已经极大地勾起了我的兴趣!找出根因,并提供解决方案,是我们在服务客户过程中的一贯态度。
3
捕捉信息
面对ORA-1000这种应用级的错误,我们一般可以通过设置errorstack时收集报错进程的process dump来进行分析;而如果报错没那么容易出现,我们就会选择在之前抛错业务频繁执行的时段做个systemstate dump,主要目的是可以看看这类业务执行时server process中都open了哪些cursor,然后根据现象进行进一步的分析,判断问题的原因;
这里客户系统是周期性的报ORA-1000错误,于是建议客户开errorstack,收集trace文件进行分析。
4
开始分析
首先是设置1000的errorstack;
ORA-1000错误发生时,会生成一个trace,通过观察trace发现在,确实打开了2000个cursor,在trace中搜索cursor#可以看到,发现cursor都是打开的同一个SQL:SELECT activityno,ruleno FROM T_RM_COUPONINF;
那么问题来了,为什么对同一个SQL会打开这么多cursor呢?仔细观察一下我们就会发现这个SQL的特别之处,Excutioncount=0&LoadCount=299&InvalidationCount=300,还记得老猫分享的第十二期的故事么,这是典型的解析错误的问题!
不过这里我们就不用设置10035事件去确认了,我们试图来解析SQL:SELECT activityno,ruleno FROM T_RM_COUPONINF;很快我们就发现了问题,T_RM_COUPONINF这个对象根本就不存在!
到这里,看起来我们发现了两个问题:
1. 进程中打开了一条错误SQL的cursor;
2. 在遇到编译错误后,进程没有及时关闭cursor,似乎对这段代码的处理过程没有加catchexecption或者finally的过程;
那么是谁发起了这条SQL,在没有编译成功的情况下,没有关闭cursor呢?模拟这样的代码一点都不难,脑子里闪过无数个草泥马…骂谁还不好说,先冷静,由于这个问题可以在测试环境重现。
5