MDA/MDD/TDD/DDD/DDDDDDD
          posts - 536, comments - 111, trackbacks - 0, articles - 0
            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

          oracle游標

          Posted on 2009-11-13 18:16 leekiang 閱讀(1170) 評論(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.aygfsteel.com/snoopy/archive/2005/01/27/744.html
          主站蜘蛛池模板: 申扎县| 武城县| 济宁市| 任丘市| 寻乌县| 响水县| 连江县| 永善县| 肥乡县| 大石桥市| 沙田区| 旌德县| 萝北县| 闵行区| 齐齐哈尔市| 乐都县| 晴隆县| 千阳县| 丰镇市| 克什克腾旗| 嘉鱼县| 德州市| 鄂托克前旗| 漾濞| 崇州市| 新乡市| 古浪县| 仁寿县| 杭锦后旗| 广元市| 建平县| 尉氏县| 布尔津县| 东莞市| 辛集市| 寻乌县| 德兴市| 台山市| 纳雍县| 林周县| 尼勒克县|