2

背景如何防止反覆自動連接到Oracle數據庫?

我們有一個C#/ VB.net客戶端應用程序消耗它可以連接到Oracle數據庫的WCF服務。 Web服務使用.NET框架的Oracle數據提供程序連接到數據庫(不要與ODP混淆)。我們的測試人員經歷了零星的Oracle帳戶鎖定,這似乎在更改用戶的Oracle密碼後不久就會發生。該DBA_AUDIT_TRAIL日誌揭示了什麼似乎在非常有規律的間隔(即在點每兩分鐘),無需任何用戶或客戶端活動將自動連接嘗試。衆多日誌(IIS,WCF跟蹤,消息日誌等)已確認這些連接嘗試不是由客戶端應用程序直接發起的;他們必須獨立於Web服務或System.Data.OracleClient庫內。自動嘗試會一直持續下去,直到Web服務的工作進程(單個工作人員)因不活動而死亡。

在某些情況下,這些自動嘗試獲取密碼更改之前開始,他們成功地連接到數據庫,但只要更改密碼,下一次嘗試爲無效的用戶名/密碼失敗。經過三次嘗試後,帳戶被鎖定。我們試圖找到這些定期連接嘗試的來源。

我發現甲骨文的論壇here非常相似,但無人接聽,問題。

當前思想

我們最新的調查已使我們相信它是連接池的意外行爲。如果用戶在密碼更改之前連接到Web服務,則會爲原始連接字符串創建連接池。在更改密碼並重新登錄到Web服務後,數據提供者將根據新的連接字符串創建一個新的連接池。

能數據提供裏面的東西是試圖保留舊的連接從第一連接池還活着嗎?也許第一個連接池將丟棄舊連接並試圖用新連接補充它(使用現在無效的連接字符串)。什麼會造成這種情況?注意:我們使用最小/最大池大小(0/100)的默認設置。

我們不相信我們的代碼是直接試圖訪問從第一連接池的連接。用戶的會話沒有任何以前會話密碼的內存,因此不會使用舊的連接字符串來引用第一個連接池。此外,我們的代碼中沒有任何內容會解釋我們所看到的非常精確的連接間隔。

+0

您可能想要轉到http://dba.stackexchange.com/ – Annjawn

+0

可能,但現在似乎是Web服務方面的一個問題。我半途期待dba.stackexchange用戶指點我回到這裏! –

回答

3

底層問題最終導致未發佈的數據庫連接。當連接打開時,它會從連接池中檢出。如果連接從未關閉,池認爲它仍在使用中。這會導致池管理邏輯使用原始連接字符串定期對數據庫進行身份驗證。密碼更改時,這很快導致登錄嘗試失敗和帳戶鎖定失敗。

// Problem logic; connection is never closed/returned to the connection pool. 
public static void ConnPoolTest1() 
{ 
    OracleConnection conn = new OracleConnection(connectionStringWithPooling); 
    conn.Open(); 

    //...Do some work 

    // Sit on this line for 5-10 minutes and examine Oracle's dba_audit_trail. 
    Console.ReadKey(); // Since connection was never released back to the connection pool, the 
         // data provider's pool management will regularly re-authenticate with DB. 
         // If user's password changes before this process dies (releasing the 
         // connection pools), you start accumulating failed password attempts. 
} 

此問題的妥善解決辦法是,以確保當你與他們所做的連接總是返回到池!

// Best practice: ALWAYS CLOSE YOUR CONNECTIONS WHEN YOU ARE DONE! 
public static void ConnPoolTest2() 
{ 
    OracleConnection conn = new OracleConnection(connectionStringWithPooling); 
    conn.Open(); 

    //...Do some work 

    conn.Close(); 

    // Sit on this line for 5-10 minutes and examine Oracle's dba_audit_trail. 
    Console.ReadKey(); // No problem here! No recurring authentication attempts because the 
         // connection has been returned to the pool. 
} 

注意:其他答案建議關閉池和清理舊的連接池的時候,密碼修改。這些建議在我們搜索未發佈的資源時爲我們提供了臨時補丁,並且他們極大地幫助我們隔離了這個問題。

+0

+1回答你自己的問題,但實際上給出了答案 – iMortalitySX

+2

其他最佳做法。任何實現IDisposable的東西進入一個使用塊。因爲我已經看到其他類似的問題沒有在網絡上回答,所以投了票。 – iivel

2

這可能有點幫助。

Oracle ODP.Net and connection pooling

OLE DB, ODBC, and Oracle Connection Pooling

基本上,在所述第二網頁在那裏,MSDN指出 「一旦被創建,連接池不被破壞,直到活性處理結束。」。看起來你的Web服務可能會持有如此多的連接/連接池,導致它存在一些問題。

所以我的建議:除了做一些更多的疑難解答,也許有些連接記錄(可能只是一個文本文件),或者第一個鏈接有一個很好的命令來跟蹤到數據庫的連接,我會試着轉現在關閉連接池。你似乎遇到的問題被稱爲「池碎片」。這是通往連接池所有數據庫連接的單臺計算機的繁忙流量。最終會出現如此多的池,導致內存問題開始出現,並且連接沒有正確關閉。如果連接沒有關閉,或者說你的密碼更改命令在使用舊連接池的其他命令列表之前執行,那麼第二個問題就是你的問題,你將遇到問題。

最終,在您的情況下,您將擁有一個創建自己的Web連接池(不是用戶)的單點(Web服務),並通過自己的連接將數據提供給用戶。這意味着必須有不同類型的身份驗證,由Web服務端處理,以處理用戶連接。我敢肯定,現在在你的模型中可能會有太多的改變,但我會強烈建議最終尋找解決方案。

+0

我同意我們結束了很多游泳池,尤其是當測試人員反覆練習更改密碼功能時,但即使在用戶終止會話後,仍然無法查看造成附加連接的原因。沒有排隊的命令等待執行(即沒有明顯的競爭條件);密碼更改在第一次會話結束後發生。我嘗試構建一個測試驅動程序來創建過多的池和連接,但我無法重現重現的自動連接。問題仍然非常不可預測。 –

+0

「在許多Web應用程序中,池碎片是一個常見問題,應用程序可能會創建大量池,直到進程退出時纔會釋放池。」我傾向於認爲這是您的問題,因爲每次更改密碼時,都會爲同一用戶創建另一個池。 ADO(這是System.Net.OracleClient在後臺使用的內容)在離開連接後即使在您關閉因爲它們位於池中而關閉後也是臭名昭着的。問題是即使你不想要,連接仍然「保持活躍」,所以「死」連接ping數據庫。 – iMortalitySX

+0

感謝您的指導。我們按照您的建議禁用了池,問題就消失了。它幫助我們確定實際的原因(未發佈的數據庫資源),作爲單獨的答案發布。 –

2

每當發生任何會導致連接無效的事件時,您都需要銷燬該池,以便池中的任何泄漏連接和/或存活被適當標記以防止重複使用。爲此,您需要使用數據提供者的clearpoolclearallpools方法。

http://msdn.microsoft.com/en-us/library/system.data.oracleclient.oracleconnection.clearpool.aspx

此外,全局異常管理器可以監聽拋出無效的用戶異常,並通過列舉標識爲連接字符串的一部分用戶的連接銷燬池。可能效率不高,但應該完成工作。

+0

我們討論過這個問題,我認爲清理舊池應該可以解決問題,但是我們現在還不能定期複製它。我希望對問題有足夠的瞭解來重現問題,並證明清理池可以解決問題。有時賬戶在被鎖定前可能會持續一兩天。其他時候,賬戶可以在一天內鎖定多次。 –

+0

您可以禁用連接池,或重載處理連接以明確確定是否存在問題。 – iivel

+0

謝謝你的建議!在我們搜索問題的來源(未發佈的數據庫連接)時,我們最終將池清理爲臨時修復,並作爲單獨的答案發布。這減輕了這個問題的短期解決方案。 –