2012-01-25 14 views
15

「プールから接続を取得する前に経過したタイムアウト期間」のエラーが表示されます。DB接続プールの漏れを見つける方法は?

クローズドdb接続を検索しましたが、見つかりませんでした。

私がしたいことは、次回このエラーが発生したときに、どのコードが問題を引き起こしているかを知ることができるprocsまたはhttp要求のリストをシステムにダンプさせます。

これらのハンドルがどれくらい保持されているかを確認することもできますので、私は使用済みだが閉じていない接続を見つけることができます。

これを行う方法はありますか?

+0

プール内の接続より多くのユーザーがいる可能性はありますか? –

+0

接続の参照をセッション状態または1つのhttp要求を超える有効期間を持つ別の場所に保存しますか? – Jan

+0

いいえ、それらは開かれたばかりで、それぞれのリクエストで(おそらく)閉じられています。 – Jesse

答えて

5

お手伝いします場合は知りません。 ".net接続プールの監視"のためのGoogleの検索を行います。

1つ前の記事Bill Vaughn's article(これは古いですが、まだ有用な情報が含まれています)を参考にしました。それは、接続プールの監視に関するいくつかの情報を持っていますが、リークがどこで発生する可能性があるかについての素晴らしい洞察もあります。

監視のために、彼は提案します。

オーケー接続プールを監視するので、あなたは、まあ。接続をオープンし、それを閉じて 接続が エアマットレスの上に接続プールで行われ、衰退にまだあるかどうかを知りたいです

・のSQLProfilerとSQLプロファイラを使用します。、 接続が所定の位置に残っているどのように多くの(まだ接続)と彼ら がやっていても何を決定するにはいくつかの方法は、私はここに、私の本の中でこれらのいくつかを議論するがありますTSQL_Replay トレースのテンプレート。プロファイラに精通している人のために、 これはSP_WHOを使用したポーリングより簡単です。各プロセスの現在の状態 を示す、すべての作業プロセスに sysprocessesテーブルからの情報を返す

・ランSP_WHOまたはSP_WHO2、。一般に、 接続ごとに1つのSPIDサーバープロセスがあります。接続文字列にアプリケーション名 引数を使用して接続名を付けた場合、簡単に見つけることができます。

・パフォーマンスモニター(PerfMon)を使用してプール と接続を監視します。私はこれについて次で詳しく議論します。

・パフォーマンスカウンターをコードで監視します。このオプションを使用すると、 に接続プール の状態と確立された接続の数を表示または単純に監視できます。これについては、このホワイトペーパーの セクションで説明します。「

編集:あなたは接続がないことを確認したら

いつものように、SO

第二編集にここother similar postsのいくつかをチェックアウトあなたが試してみることのできるもう一つの方法は、StateChangeイベントを利用して、いつ接続を開いたり閉じたりしているかを確認することです。状態が閉じた状態よりも開いた状態に変化した場合、それはどこかにリークがあることを示します。また、statechangedイベントのデータをタイムスタンプと共にログに記録することもできます。アプリケーションに他のログがある場合は、状態が変更されて開いているように見えるインスタンスのログファイルを解析することもできます。対応するオープンからクローズへの対応はありません。 StateChangedEventを処理する方法の詳細については、this linkを参照してください。

+0

接続がプール内で開いたままになっている場合、SQLプロファイラが孤立しているときにどのように表示されますか?私が望む情報がデータベースにはないが、プール管理層にあるようだ。 – Jesse

+0

SQLプロファイラオプションについては、接続プールの監視には使用していないため、コメントできません。 PerfMonとパフォーマンスカウンターから得られる情報の種類に関する詳細情報(彼が最後に話したカップルについては、を参照してください)。 **これらの唯一の** **あなたは**恐ろしいエラーが表示されます**あなたは**彼らが孤児になったとは言いません。私はパフォーマンスカウンターを使用してデータをポーリングしました。 –

+0

Hmm。私が探していた銀色の弾丸ではありませんでしたが、徹底した説明に感謝します! – Jesse

0

私は長い間、私は当時仕事とSPと呼ばれる方法を見つけることができ、前にストアドプロシージャを実行している見つけるために、この

http://www.simple-talk.com/sql/performance/how-to-identify-slow-running-queries-with-sql-profiler/

を使用しました。

はそれが接続プールを監視するためのいくつかの良いリンクがあります

+0

問題は(私は)思っていますが、遅い実行クエリではありません。クエリを実行するコードを使用しているため、dbハンドルを放棄しません。 – Jesse

13

接続の作成/オープンが一元管理されている場合は、次のクラスでは漏れた接続を見つけることが容易になります。お楽しみください:)

/// <summary> 
/// This class can help identify db connection leaks (connections that are not closed after use). 
/// Usage: 
/// connection = new SqlConnection(..); 
/// connection.Open() 
/// #if DEBUG 
/// new ConnectionLeakWatcher(connection); 
/// #endif 
/// That's it. Don't store a reference to the watcher. It will make itself available for garbage collection 
/// once it has fulfilled its purpose. Watch the visual studio debug output for details on potentially leaked connections. 
/// Note that a connection could possibly just be taking its time and may eventually be closed properly despite being flagged by this class. 
/// So take the output with a pinch of salt. 
/// </summary> 
public class ConnectionLeakWatcher : IDisposable 
{ 
    private readonly Timer _timer = null; 

    //Store reference to connection so we can unsubscribe from state change events 
    private SqlConnection _connection = null; 

    private static int _idCounter = 0; 
    private readonly int _connectionId = ++_idCounter; 

    public ConnectionLeakWatcher(SqlConnection connection) 
    { 
     _connection = connection; 
     StackTrace = Environment.StackTrace; 

     connection.StateChange += ConnectionOnStateChange; 
     System.Diagnostics.Debug.WriteLine("Connection opened " + _connectionId); 

     _timer = new Timer(x => 
     { 
      //The timeout expired without the connection being closed. Write to debug output the stack trace of the connection creation to assist in pinpointing the problem 
      System.Diagnostics.Debug.WriteLine("Suspected connection leak with origin: {0}{1}{0}Connection id: {2}", Environment.NewLine, StackTrace, _connectionId); 
      //That's it - we're done. Clean up by calling Dispose. 
      Dispose(); 
     }, null, 10000, Timeout.Infinite); 
    } 

    private void ConnectionOnStateChange(object sender, StateChangeEventArgs stateChangeEventArgs) 
    { 
     //Connection state changed. Was it closed? 
     if (stateChangeEventArgs.CurrentState == ConnectionState.Closed) 
     { 
      //The connection was closed within the timeout 
      System.Diagnostics.Debug.WriteLine("Connection closed " + _connectionId); 
      //That's it - we're done. Clean up by calling Dispose. 
      Dispose(); 
     } 
    } 

    public string StackTrace { get; set; } 

    #region Dispose 
    private bool _isDisposed = false; 

    public void Dispose() 
    { 
     if (_isDisposed) return; 

     _timer.Dispose(); 

     if (_connection != null) 
     { 
      _connection.StateChange -= ConnectionOnStateChange; 
      _connection = null; 
     } 

     _isDisposed = true; 
    } 

    ~ConnectionLeakWatcher() 
    { 
     Dispose(); 
    } 
    #endregion 
} 
+0

これは、開かれていて決して閉じられなかった接続を見つけるのに役立ちました。本当にクールなクラス:)ありがとう! – Challe

+0

素晴らしい!これを知ってうれしいことは、他人に役立つかもしれない。 – LOAS

関連する問題