MDA/MDD/TDD/DDD/DDDDDDD
posts - 536, comments - 111, trackbacks - 0, articles - 0
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

oracle游标

Posted on 2009-11-13 18:16 leekiang 阅读(1154) 评论(0)  编辑  收藏 所属分类: oracle
使用ORACLE数据库的游标错误( maximum open cursors exceeded )
最近开发第一次遇到“ maximum open cursors exceeded”这个错误。表示已经达到一个进程打开的最大游标数
游标:当返回一个含有多条记录的结果集时,游标就像指向结果集中当前记录的指针,通过游标我们可以处理结果集中的每一条记录。
对于出现ORA-01000 maximum open cursors exceeded错误这种情况,单纯的加大open_cursors并不是好办法,那只是治标不治本。实际上,代码中的隐患并没有解除。 而且,绝大部分情况下,open_cursors只需要设置一个比较小的值,就足够使用了,除非有非常特别的要求。

从网上查了一下这个错误的原因,主要还是代码问题引起的。

这样的错误很容易出现在Java代码中的主要原因是:Java代码在执行 conn.createStatement()和conn.prepareStatement()的时候,实际上都是相当于在数据库中打开了一个 cursor。尤其是,如果你的createStatement和prepareStatement是在一个循环里面的话,就会非常容易出现这个问题。因为游标一直在不停的打开,而且没有关闭。

一般来说,我们在写Java代码的时候,createStatement和prepareStatement都应该要放在循环外面,而且使用了这 些Statment后,及时关闭。最好是在执行了一次executeQuery、executeUpdate等之后,如果不需要使用结果集 (ResultSet)的数据,就马上将Statment关闭。

我就是在循环里调用con.prepareStatement(sql)导致的这个错误。
修改方法,
在遍历完ResutSet后关闭rs和stmt就可以了。

转自http://ltc603.javaeye.com/blog/71540


一般来说是游标不够用了。
只需在initSID.ora文件中加上一行
open_cursors = ****
但是,很可能是由于你的程序或数据库的结构存在着一些潜伏的问题,如jlandzpa所说,没有关闭游标等。

我的程序有一阵一直在报这个错误,把OPEN_CURSOR加大到了300甚至1000还在出错,后来发现是表的STORAGE设置有问题。

建议你查一下自己的程序。
昨天说的有些错误,应该是physical_attributes_clause语句。

我们系统的数据量比较大,近200张表,有些表一天要插入1000000条左右的数据。

表是使用ER/STDIO设计的,然后直接生成建表的脚本,由于没有设置physical_attributes_clause语

句中的建表参数,因此使用了默认的参数。好像是INITIAL 10K NEXT 10K PCTFREE 20 PCTUSED 50

由于表的存储空间太小,在很短的时间内就会装满,因此ORACLE就需要不停为30多张表(数据量较大的)申请空间。于是在程序运行了一段时间后,开始出现ORA-01000: maximum open cursors exceeded的错误。 我将游标大小改到了300,还是出现错误,改到1000以后开始出现了ORA-01001:invalid cursors。再怎么加大open_cursors的数量都无济于事。

使用select * from v$open_cursors查询,发现有几百条的INSERT语句游标没有释放。

开始怀疑是程序调用的问题,仔细检查程序没有发现问题。但是发现对某张表进行TRUNCATE操作后,对此表进行插入的游标全部释放,于是开始怀疑是表结构本身的问题。

重新设置了建表参数,将数据量最大的表的INITIAL和NEXT均设置为50M。

至今未再出现同样的错误。

再次提问ORA-01000: maximum open cursors exceeded问题

这个问题yangtingkun讲的非常详细,使我茅塞顿开,但我还有一些问题向诸位高人请教。
我这里出的问题也是ORA-01000: maximum open cursors exceeded ,我将游标数由300提高到500仍然不能解决这个问题。看了这篇帖子我非常高兴,但有一些问题不明白。
我使用了select * from v$open_cursor进行查询后看不出来哪些游标未被释放。一共有近4000条记录,hash_value字段象特殊点,值从几万到几百万都有,请问怎样判定哪些游标未被释放,有多少。
另外请教一下,怎样重新设置了建表参数,能指点一下所需命令吗。数据库里表数量极大,怎样找到数据量最大的表啊。
我是菜鸟,请不要见笑。不吝赐教。

首先通过v$open_cursor中的SQL_TEXT字段可以查出没有释放的SQL是大致是什么语句。

由于建表参数设置不当,会有很多的INSERT语句无法释放。

SELECT * FROM V$OPEN_CURSOR WHERE SQL_TEXT LIKE 'INSERT%‘

找一找哪些表的INSERT语句没有释放的游标比较多。
从ALL_TABLES里查看该表的建表参数是否合适。

ALTER TABLE tablename STORAGE( NEXT N);

建议加入精华区,我也碰到同样的问题。也是调整的存储结构,另外调整了一些索引和程序,一直不知道是存储结构的问题,调整的东西多,就不知道是什么原因了

原帖由 becochow 于 2009-3-25 18:56 发表
我也出现这样的问题,我现在数据库在运行,可能是存储过程中未关闭游标,

我如何手动关闭呢?查询v$open_cursor 有几千条

今天我也碰到了这个错误,我这么关闭的:
查询v$open_cursor,看哪些是由于"存储过程中未关闭游标"引起的会话,找到SID,SERIAL#,然后KILL掉就可以了.
以上来源于http://www.itpub.net/viewthread.php?tid=24806



我昨天犯的错误就是把创建statement放到了循环之内,结果导致cursor猛增,到达了数据库设置的最大数。
虽然解决了问题,也清楚了游标是何时创建的,但还有几个问题比较迷糊。
1、通过查询,JDBC是将所有的查询结果一次性放到ResultSet中,还是一次只放一定数目的记录?例如,查询结果为2000条数据,JDBC是一次性将2000条数据放到结果集中,还是分批放置呢?

2、当通过ResultSet.next(),移动结果集指针时,此时是否还与数据库发生交互?


首先结果集resultset在你的java程序处。其中有个fetchsize设置,这个表示每次从数据库处取多少条记录到resultset.
当通过ResultSet.next(),移动结果集指针时,此时是否还与数据库发生交互?

不发生交互,数据库执行完查询后,已经把查询结果交给ResultSet了,以后的操作,和数据库无关。
交互,如果1个查询有10000条记录,resultset中只有fetchsize条,当next时还会在一定时机去交互
不是将查询结果一次性放到ResultSet中, 而是分批放入ResultSet中,一般情况下是每次10条记录.
当通过ResultSet.next(),移动结果集指针时,此时还会与数据库发生交互.

导致maximum open cursors exceeded这个问题一般是代码本身的问题.
比如执行一个查询没有关闭游标,或是在存储过程中打开了游标而没有关闭.
特别是出现异常情况是没有关闭游标.严重时会导致系统崩掉
啊~!~`我刚也犯了这种错误!!``看到这里的贴子,小妹又明白了:"哦!``原来conn.createStatement()和 conn.prepareStatement()的时候实际上都是相当与在数据库中打开了一个cursor。!!"明白了这点过后,我就在循环里新建一个 prepareStatement对象,操作完一次,成功过后就马上关掉!这样,循环里每次一个insert都新new 一个prepareStatement 操作成功完成之后再马上关闭.嘎嘎.~这样,cursor就不会溢出拉.
http://www.blogjava.net/snoopy/archive/2005/01/27/744.html

只有注册用户登录后才能发表评论。


网站导航: