分类: Oracle
2008-04-11 21:12:14
来源:华夏学习网 作者:bushi |
ORA-00604 error occurred at recursive SQL level string
Cause:An error occurred while processing a recursive SQL statement (a statement applying to internal dictionary tables).
Action:If the situation described in the next error on the stack can be corrected, do so; otherwise contact Oracle Customer Support.
ORA-00604: 递归某个SQL 层时出现错误
原因:在运行一条递归SQL语句(该语句将应用于对内部表或数据字典的操作)时,发生错误。
方案:如果上述描述的错误所在栈可以被修复,则修复并继续运行;否则,请联系Oracle客服。当然,那是Oracle官方的解决办法。我曾经记得有个高手总结了关于ORA-00604/ORA-04031问题的解决:
修改INIT.ora
添加
并重新启动数据库.
分析:ORA-00604这个信息表明,在数据库执行内部SQL语句时,发生了错误。比如,要往表中插入一行数据,但没有可扩展的空间。ORACLE于是去查寻,哪儿可以建立下一个扩展空间,它有多大小,但没有成功。一般在发生ORA-00604错误时,还伴随着其它的错误,例如:ORA-1547等。
首先,应当检查警告文件alertSID.log,查找有关ORA-600类的信息。
该错误最常见的原因是数据库文件initSID.ora中的参数OPEN_CURSORS值太小。可以修改initSID.ora文件,OPEN_CURSORS的值一般为255。修改完后,宕下ORACLE,再重新启动。
还可以设置并启动数据库的事件跟踪功能。在initSID.ora中加上一行:
宕下并重新启动ORACLE,使这个事件跟踪参数起作用。这样,当再发生ORA-604错误时,有关信息就保存在TRACE文件中。
造成ORA-604错误的其它原因可能有:
- initSID.ora中,参数DC_FREE_EXTENTS或ROW_CACHE_ENQUEUES太低。可以根据操作系统和数据库的情况,适当增加这两个参数的值,宕下并重新启动ORACLE。
- 运行超出空间(伴随ORA-1547错误)。这时,要对表空间添加新文件,即增加表空间的大小。
- 达到了MAX_EXTENTS(伴随ORA-1556错误)。如果这样,就要修改表,允许更多的扩展。请从技术手册中查找MAX_EXTENTS的最大值。如果已经达到了最大值,必须用compress extents选项,把表卸出(export),再导入(import)数据库中。
案例一:Oracle执行递归查询的时候出错
问题描述:我经常遇到ORA-00604 和ORA-01000(开启游标数量达到最大值)错误。然而,当我检查代码的时候,所有的结果集和语句对象都在最后的块中关闭了(我使用的是JDBC)。我执行的查询是一个Oracle递归查询(以这个开始并通过这个连接)。您能告诉我是哪里出现了问题,以及在什么样的情况下会出现上述的错误吗?
解决方案:可能是init.ora 文件中的open_cursors 参数值的设置太低了。这个参数的默认值是非常低的(50)。它应该设置为200或者更高。即使是你关闭了结果集,但是你并没有在JAVA代码中关闭SQL语句,就会导致这个问题。
如果设置为yes的话,那么确保你的活动连接池启用了(为了性能的原因),否则设置为no。
请你的数据库管理员监视数据库,并看看使用V$OPEN_CURSORS 和 V$SYSSTAT数据字典视图的条目。 |
案例二:Exp出错的一个案例
问题描述:客户用的Linux系统,Redhat 企业版(RHEL 3.0).数据库,安装的9iR2, 前一段时间升级过.现在的版本是9204.
客户准备要做Exp导出,以前一直系统没有空间.先给给系统扩了一些空间。Linux下的LVM还算比较好用。虽然文件系统用的是ext3 ,要暂时停机.
进行导出操作,不成功,发现系统报告错误:
|
很多朋友可能对这个错误都很熟悉.
哦,对了,客户说是升级过数据库,首先猜测是不是升级有问题?毕竟在论坛上类似升级不成功的问题看过很多了.
执行$ORACLE_HOME/rdbms/admin/catpatch.sql 脚本.
同时要注意调大java_pool_size 和shared_pool_size这两个参数的大小,要不重新来就耽误时间了,不要犯低级错误
|
之后查看Spool 出来的日志. 发现有编译错误,重新执行了第二次. 等待......之有这个时候我才想起才抱怨CPU不够快,内存不够大 ;)
这次Log没错误.不料想....................用户连接报告错误:
|
发现connect / as sysdba 还是可以登陆进去的。
看来是 LBACSYS.LBAC_EVENTS的状态有点问题。联接进去,编译一下如何? 我的如意算盘是@?/rdbms/admin/utlrp.sql执行一下就没有问题了,不料根本没有用,错误依然。当时有些头晕,这系统还没有备份呢,看来有些麻烦了(心里暗地埋怨客户,一直不让备份,总说"等等再说",作为一个DBA说话总不被重视也挺悲哀的不是? ,虽然我自己偷着有个备份,不过还是上次升级时候的呢),赶紧上网Metalink查查,这里网络速度还不错 LBACSYS.LBAC_EVENTS 作为关键词,找到如下的信息:
|
解决方案:
|
支持人员说这是个Bug.但是普通用户不可见. 不太放心,再找找,在Suse.com站点的Maillist也发现了一则类似的案例,看来还可以,心里有底了。
按照上面的执行,重新检查,OK。
总结一下
其实是一个很没有技术含量的Case。首先以前升级的时候至少要测试一下Export是否可以(Export已经成为升级成功的一个标志了!) 其次,准备不够充分,早成了手忙脚乱.所幸不是关键系统,用户还可以容忍.Oracle 总说微软是个烂公司,其实他们才真的够栏.Bug多的不可胜数.
案例三:使用网络应用程序的时候出现递归SQL错误
问题描述:当我使用网络应用程序的时候,遇到了下面的这个错误。
ORA-00604: 递归SQL1级的时候出现错误。
ORA-04031: 无法分配4200字节的共享内存,"RBKS_BK_INFO", "sga_heap", "library cache"。
这些错误信息是什么意思?我该如何解决它们?它们是在应用程序里面还是数据库里面?
解决方案>:您应该使用的是Oracle 8.1.7.4之前版本的Oracle。第一个错误信息告诉你Oracle针对你的行为执行的SQL 语句失败了。ORA-4031告诉你为什么它会失败。ORA-4031错误信息的意思是你没有获得足够的空闲空间。你可以增加你的SHARED_POOL_SIZE,重新启动数据库再拭一次。这个bug已经在后续的补丁包中修复了。如果你使用的不是这个版本,你可以应用一下补丁包。
案例四:Sql_trace进行Oracle诊断案例
问题说明:很多时候,在我们进行数据库操作时,比如drop user,drop table等,经常会遇到这样的错误
ORA-00604: error occurred at recursive SQL level 1 .
这样的提示,很多时候是没有丝毫用处的.本案例就这一类问题提供一个思路及方法供大家参考.
1. drop user出现问题
报出以下错误后退出
ORA-00604: error occurred at recursive SQL level 1
ORA-00942: table or view does not exist .
关于 recursive SQL 错误我们有必要做个简单说明.
我们知道,当我们发出一条简单的命令以后
Oracle数据库要在后台解析这条命令,并转换为Oracle数据库的一系列后台操作.
这些后台操作统称为递归sql.
比如create table这样一条简单的DDL命令,Oracle数据库在后台,实际上要把这个命令转换为对于obj$,tab$,col$等底层表的插入操作.Oracle所作的工作可能比我们有时候想的要复杂的多.
2.跟踪问题
我们知道Oracle提供sql_trace的功能
可以用于跟踪Oracle数据库的后台递归操作.
通过跟踪文件,我们可以找到问题的所在
以下是格式化(tkprof)后的输出:
|
Oracle把错误信息首先呈现出来,我们看到ORA-00942错误是由于SDO_GEOM_METADATA_TABLE表/视图不存在所致,问题由此可以定位.
对于这一类的错误,定位问题以后解决的方法就要依据具体问题原因而定了。
3.问题定位
对于本案例,通过Metalink获得以下解释:
|
(1)
|
对于本例,为MDSYS.SDO_GEOM_METADATA_TABLE创建一个同义词即可解决,是相对简单的情况.
(2)
|
4.实际处理
MDSYS.SDO_GEOM_METADATA_TABLE为Spatial对象
如果未使用Spatial选项,可以删除
|
这时用户得以顺利drop
5.一点总结
使用sql_trace可以跟踪数据库的很多后台操作有利于我们发现问题的所在,很多时候,我们想要研究Oracle的内部活动或后台操作,也可以通过sql_trace跟踪,sql_trace/10046 是Oracle提供的最为有效的诊断工具之一.
案例五:表更新时发生递归SQL2级失败错误
问题描述:表更新的时候失败了,并且生成了一条ORA-00604 错误信息。这个错误发生在递归SQL 2级。
解决方案:不幸的是,这个错误并不能告诉你Oracle数据库在错误发生的时候正要做什么。当你执行一条SQL语句的时候,Oracle数据库辉为你在幕后做很多事情。例如,考虑下面的SQL语句:
|
这条SQL语句给号码为1001的雇员涨5%的工资。当你执行这条语句的时候,Oracle查询数据目录来确定是否有这个表或者你是否使用了同义字。一旦它找到了数据库对象,Oracle查询数据字典来判断你是否拥有访问这个对象的权限。那么,Oracle到底是如何与数据字典进行交互的呢?它执行一条自己的SQL 语句。这些Oracle为你执行的SQL语句被称为“递归”SQL语句。你最初的SQL 语句是0级。Oracle为你执行的递归SQL语句是1级。有时候,一条递归SQL语句又会引起自己的递归SQL语句,就是2级。
在你的案例中,有一个2级的递归SQL语句正在执行,并且产生了问题。为了解决问题,你需要找出执行的是什么递归SQL语句引起的错误。要做到这一点,你必须启动会话中的追踪。首先,执行下面的SQL 语句:
|
然后,执行你的更新语句。你会看到ORA-604 错误。接下来,执行下面的语句:
|
现在到你为数据库定义的USER_DUMP_DEST 起始参数上的路径去。那里应该有一个时间戳为当前时间的文件。那个就是你生成的追踪文件。你可以打开文件并检查递归SQL语句,其中包括引起错误的一条。(接近追踪文件的末尾)。
案例六:连接数据库用户的时候遇到ORA-00604错误
问题描述:当我试图连接到数据库用户的时候,得到了如下的错误信息:ORA-00604:递归SQL 1级的时候出现错误。但是如果我使用数据库管理员的角色的时候,用户就能够连接。系统用户可以连接,但是scott 就不能连接。
解决方案:Oracle为你在幕后做了很多的工作。它在自己的SQL 语句的全过程中进行这项工作。Oracle发布给你的任何的SQL 语句都是“递归的SQL”语句。应该有很多的SQL 语句会引起你遇到的问题。我建议你所做的就是在INIT.ORA文件中设置SQL_TRACE=TRUE,然后重新启动数据库。然后复制ORA-604错误。这会在你的USER_DUMP_DEST目录中生成所有用户进程的大量追踪文件。在错误发生之后,立即关闭数据库,并设置SQL_TRACE=FALSE。然后再一次启动数据库。现在通过追踪文件,你就可以USER_DUMP_DEST目录中生成的追踪文件中查找ORA-604错误那一条信息。就在那里,你就发现ORA-604错误是哪一个递归SQL语句产生的,以及实际发生的错误情况。你的解决方案依赖于语句和实际的错误。
案例七:有人Move了系统表Dependencie$表, Crash了
今天有人问我这样之后能不能恢复, 我想基本上已经不能了. 在open时报ORA-01092号错误, 我查了一下event也没有这方面的合适的event啊, 我推荐用不完全恢复, 不过好象是没有备份, 运行在noarchivelog模式.
从trc文件中得到的内容:
|
DBA做事一定要细心, 在运行批处理时一定要审了再审.
补充:
后来我用AnySQL UnLoader去恢复数据了, 和客户一起花了24小时, 最后他们说OK了.
Eygle和Chensq对这个问题也有研究, 他们想出了更好的办法解决此事, 不过最后原来的库肯定是不能再用了, 必须要exp/imp到别的库了, 我是用AUL帮客户恢复数据的, 数据量在30G以上.
案例八:ORA-00604:递归SQL产生的错误
问题描述:我有一个Pro*c 的程序,有时候会给出下列的错误信息:
ORA-00604:递归SQL 1级上产生错误
你能告诉为什么会出现这个错误,它什么时候出现,以及可能的解决方案是什么吗?
解决方案:无论你什么时候执行查询,系统都会在后台执行一些查询来判断许多事情,例如“你是否有权限来执行这个查询?”,“你要访问的这个对象是否存在?”。这些系统执行的查询被称为“递归SQL”。有时候,一个递归SQL语句需要调用自身的递归SQL。那么这些执行的递归SQL语句就是另一个级别的,2级。
你不会在SQL*Plus 中看到递归SQL语句。要查看它们的最好的方式就是开启会话中的追踪。启动SQL*Plus ,执行下列命令:
|
然后运行你的进程,直到崩溃。继续,并关闭SQL*Plus 。现在到USER_DUMP_DEST 目录中。那里会生成一个追踪文件给你。查看追踪文件中的有关ORA错误的信息。这就是问题产生的根源。纠正ORA错误就会防止ORA-600错误再次出现。
大多数的ORA-600错误都可以通过以SYS登录,并从ORACLE_HOME/rdbms/admin 运行CATALOG 和 CATPROC 来予以纠正。