使用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.tkk7.com/snoopy/archive/2005/01/27/744.html