2012-01-20 109 views
4

我們有ASP.NET應用程序連接到odp.net的oracle數據庫。Oracle連接不關閉

最近我們開始遇到一些性能問題。看起來Oracle連接不會關閉,並最終堆積起來,直到它崩潰我們的網站。

作爲第一步,我們做了代碼審查,並確保在執行後關閉所有打開的連接。

OracleConnection cn = Helpers.ConnectToDB(); 
    try 
    { 

     cn.Open(); 
     //do somtehing 
    } 
    catch (Exception ex) 
    { 
     //log error 
    } 
    finally 
    { 
     cn.Close(); 
     cn.Dispose(); 
    } 

,但沒有幫助,每天幾個小時的連接堆積如山,崩潰我們的網站。

這裏是連接從昨天登錄:發生在14時27分44秒,然後重新啓動連接開始下拉申請後

TO_CHAR(DATE_TIME,'DD/MM/YYYY MACHINE STATUS CONNECTIONS 
19/01/2012 14:40:03 WORKGROUP\OTH-IIS-1 ACTIVE 1 
19/01/2012 14:38:00 WORKGROUP\OTH-IIS-1 ACTIVE 2 
19/01/2012 14:35:57 WORKGROUP\OTH-IIS-1 ACTIVE 2 
19/01/2012 14:34:55 WORKGROUP\OTH-IIS-1 ACTIVE 28 
19/01/2012 14:33:54 WORKGROUP\OTH-IIS-1 ACTIVE 26 
19/01/2012 14:31:51 WORKGROUP\OTH-IIS-1 ACTIVE 34 
19/01/2012 14:30:49 WORKGROUP\OTH-IIS-1 ACTIVE 96 
19/01/2012 14:29:47 WORKGROUP\OTH-IIS-1 ACTIVE 73 
19/01/2012 14:28:46 WORKGROUP\OTH-IIS-1 ACTIVE 119 
19/01/2012 14:27:44 WORKGROUP\OTH-IIS-1 ACTIVE 161 
19/01/2012 14:26:43 WORKGROUP\OTH-IIS-1 ACTIVE 152 
19/01/2012 14:25:41 WORKGROUP\OTH-IIS-1 ACTIVE 109 
19/01/2012 14:24:40 WORKGROUP\OTH-IIS-1 ACTIVE 74 
19/01/2012 14:23:38 WORKGROUP\OTH-IIS-1 ACTIVE 26 
19/01/2012 14:22:36 WORKGROUP\OTH-IIS-1 ACTIVE 2 
19/01/2012 14:21:35 WORKGROUP\OTH-IIS-1 ACTIVE 2 

崩潰點。

我們使用連接字符串是:

<add name="OracleRead" connectionString="Data Source=xxx;User Id=yyy;Password=zzz;Max Pool Size=250;Connection Timeout=160;" providerName="Oracle.DataAccess"/> 

那麼這裏的問題是什麼?

我們需要定義或更改這些屬性中的一種:

Connection Lifetime, Decr Pool Size, Max Pool Size, Min Pool Size? 

什麼是在這種情況下建議的設置?

+1

你連接實際上沒有「Pooling = True;」,它甚至使用連接池?你有沒有嘗試過「Pooling = True」在連接字符串中。 –

+0

Pooling = True是默認值 –

+0

您是否設法解決這個問題? – Robbie

回答

1

確保在try/finally塊中包含所有連接。僅僅爲每個.Open()調用.Close()是不夠的。您必須將.Close()調用放在finally塊中。最簡單的方法是使用使用塊創建連接。

+0

Joel - 我們進行了代碼審查,並確保在用try,catch和finally執行後關閉所有打開的連接。 –

+0

這對我來說還是不清楚,你做得對。您的評論聽起來像try/catch /最終只發生_after_執行您的查詢,而_only_涵蓋'.Close()'調用。查詢執行_must_位於'try'塊內,'.Close()'調用_must_位於相應的'finally'塊內。如果是這種情況,請確保這是明確編輯到您的原始問題。我認爲你可能確實是對的,但在我們開始研究其他問題之前,我需要確定。如果這在一個地方是錯誤的,那幾乎肯定是罪魁禍首。 –

+0

喬爾 - 見我的編輯。 –

1

嘗試包裝你的OracleConnection使用using塊裏面(如果你使用C#):

using (OracleConnection conn = new OracleConnection(connectionString)) 
{ 
    ... 
} 

這將確保它得到妥善處置,當你用它做的。 OracleConnectionOracleDataReader(作爲另一個例子)執行IDisposable,因此應在using聲明中使用。

+1

我在OracleConnection實現IDisposable的文檔中找不到 - 您能否顯示一些相關鏈接? –

3

您需要顯式處理所有Oracle.DataAccess對象,包括Connections,Commands和Parameters。

見註釋中的代碼示例在這裏:

https://nhibernate.jira.com/browse/NH-278

一對夫婦的其他注意事項:

  • 儘量使用關鍵字,因爲這將即使在特殊情況下,保證處置
  • ODP參數對象是特殊的(與常規的ADO.NET參數約定相比),因爲它也需要顯式處理(例如,SQL Server版本不需要)
2

我知道這個問題很老,但我找到了一個解決方案,似乎爲我工作。

我的解決方案是調用一個ASHX處理程序,然後返回一個圖像,平均而言,此服務在每頁加載某個頁面的10-14次之間調用。

我對64位使用ODP.NET Oracle.DataAccess.Client命名空間V4.112.3.60。

我有我所有的代碼使用語句(這裏混淆):

using (OracleConnection conn = new OracleConnection(System.Web.Configuration.WebConfigurationManager.ConnectionStrings["####"].ConnectionString)) 
{ 
    using (OracleCommand cmd = new OracleCommand(query, conn)) 
    { 
     OracleParameter p = new OracleParameter("####", OracleDbType.Varchar2, 10); 
     p.Direction = ParameterDirection.Input; 
     p.Value = val; 

     cmd.Parameters.Add(p); 
     conn.Open(); 
     using(OracleDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection)) 
     { 
      if (reader.HasRows) 
      { 
       while (reader.Read()) 
       { 

        OracleBlob lob = reader.GetOracleBlob(0); 
        //OracleLob lob = reader.GetOracleLob(0); 
        srcImage = new Bitmap(lob); 
       } 
       newImage = resizeImage(srcImage, new Size(120, 150)); 
       newImage.Save(context.Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg); 
      } 
      else 
      { 
       srcImage = new Bitmap("Images/none.jpg"); 
       newImage = resizeImage(srcImage, new Size(120, 150)); 
       newImage.Save(context.Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg); 
       ProcessError(ref context, 500); 
      } 
     } 
     p.Dispose(); 
    } 
} 

我嘗試了很多東西:

  • 檢查其他連接打開的同時
  • 重新寫一個SQL數據源控件,以便我對連接有更多的控制
  • 使用System.Data.OracleClient)

但是,當涉及到逐句通過代碼時,我發現有時代碼不會到達使用塊的末尾,並且下一個請求會在處理程序到達結束點之前進入處理程序(我在猜測某些內容與max請求處理?),這導致一些會話在V $ SESSION中保持打開,我必須手動關閉。

我碰到這段代碼:

OracleConnection.ClearAllPools(); 

並試圖運行它,雖然會議將通過處理程序保持開放,至少這些將這段代碼封閉,目前運行在OracleConnection的使用塊的結尾(因此每次調用該服務時都會清除這些池,希望處理程序能夠執行這些操作!)。

所以使用ClearAllPools方法似乎可行,但我知道這不是理想的解決方案。

+0

可能值得說的是,這會減緩從處理程序中獲取數據的速度,可能會降低大約一秒。我猜這是因爲它必須創建一個新的會話,因爲最後一個被關閉,因爲我把OracleConnection.ClearAllPools()放在了哪裏。 – Robbie

+0

我有類似的問題。當我在oracle中調用SP時,它會在會話瀏覽器中檢入時創建40個以上的進程。它甚至在使用「using」或「oracleConnection.close()和dispose()」之後也不清楚。所以暫時我不得不使用OracleConnection.ClearPool(oraConn)。感謝您的代碼。同時,您是否找到了不同的解決方案或此問題? – superachu

+0

不是,這花了我很長時間,以至於我沒時間找到改進它的方法。我不知道每次我們進行數據庫調用時,調用OracleCOnnection對象時調用ClearAllPools()的資源成本是多少... 我幾乎願意假設它是我的代碼中的某些東西,但它看起來很緊張,我想說的唯一原因是因爲我沒有找到其他人有同樣的問題。我的情況是 – Robbie