Oracle運維日記

前言

最近實驗室一直的一個運維項目頻頻在Oracle上出錯,想着錯誤還挺典型,做一個記錄,以供後續參考學習使用。 

運維記錄

1. ORA-01000: 超出打開遊標的最大數

問題描述:需要開多進程遍歷對象集合,並且將對象數據存入到Oracle數據庫中,測試報超出Oracle遊標最大數的錯誤。

知識介紹:

Oracle的遊標數cursors:遊標是SQL的一個內存工作區,由系統或用戶以變量的形式定義。遊標的作用就是用於臨時存儲從數據庫中提取的數據塊。在某些情況下,需要把數據從存放在磁盤的表中調到計算機內存中進行處理,最後將處理結果顯示出來或最終寫回數據庫。這樣數據處理的速度纔會提高,否則頻繁的磁盤數據交換會降低效率。(參考https://www.cnblogs.com/guohu/p/11007352.html

遊標一旦打開,數據就從數據庫中傳送到遊標變量中,然後應用程序再從遊標變量中分解出需要的數據,並進行處理

一般Oracle默認遊標數OPNE_CURSORS爲300(足以夠用),最大爲1000

解決方法:

1. 手動在Oracle中增大遊標數

//查看系統配置遊標數法1
select value from v$parameter where name = 'open_cursors';
//查看系統配置遊標數法2
show parameter open_cursors;

//查看當前被打開的遊標個數
select count(*) from v$open_cursor;

//修改Oracle遊標數
alter system set open_cursors=1000 scope=both;

2. 程序中及時釋放資源,這裏需要明確一般釋放的順序是ResultSet(如果用到的話)、PreparedStatement、Connection。

如果沒有釋放prepareStament就關閉了connection,雖然看起來是釋放了資源,但是遊標數並沒有得到釋放,如果數據量請求量特別大的情況下,每次請求都沒有釋放遊標數,就有可能導致最終Oracle提供的遊標數被佔滿從而報ORA-01000的錯誤。

參考https://blog.csdn.net/wodestudy/article/details/23887279?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task

一般有的可能有二:

1) 關閉Connection(將連接放入連接池)前未關閉PreparedStatement(即遊標)

2) 在循環體中使用connection.prepareStatement(sql)初始化preparedStatement對象後,未在循環體執行完增/刪/改/查後及時關閉到PreparedStatement,導致數據量過大的時候遊標不夠用

for(int i = 0; i < vos.size(); i++){
    preparedStatement = connnection.prepareStatement(sql);
    preparedStatement.setString(1,vos.getXXX());
    preparedStatement.setString(2,vos.getXXX());
    preparedStatement.setString(3,vos.getXXX());
    preparedStatment.executeUpdate();
    //打開遊標後使用完及時關閉
    if(preparedStatement != null){
        prepatedStatemnet.close();
    }
}

此處需要注意的是將程序修改爲及時關閉遊標,但是在多進程併發執行的過程中還是有可能出現ORA-01000的錯誤,這是因爲oracle給的遊標數就是那麼大,如果當前進程數比較大所有的遊標數都被佔了,那麼在有遊標被釋放前會有一段時間資源被用完線程無法執行,等待有遊標可用時即可繼續執行。

總結

以問題爲索引,不斷學習,不斷進步。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章