1. ホーム
  2. データベース

Net connection pool configuration Timeout expired. 操作の完了前にタイムアウト時間が経過したか、サーバーが応答していない。"

2022-03-20 22:20:49

Net connection pool configuration Timeout expired. 操作の完了前にタイムアウト時間が経過したか、サーバーが応答していません."

Net は、データベース操作時にデフォルトでコネクションプールを開くため、手動で設定する必要がありません。この機能はデータベース操作をより効率的にすることができますが、プログラムを真に効率的にするためには、それと連動するコードも必要です。

1. 接続文字列

    ADO.Netの接続プールのサイズは、データベース接続文字列で制御することができます。

string cs =
    "server=. ;uid=sa;pwd=tcaccp;database=pubs;pooling=true;min pool size=5;max pool size=10"

    ここで、pooling は接続プーリングをオンにするかどうかを示します。デフォルトはオンで、オフにするには pooling = false が必要です。

    min pool size は、接続プールに保持される接続オブジェクトの最小数を示します。

    max pool size は、コネクションプールに保持されるコネクションの最大数を示します。(最大値は0にすることはできず、また最小値より小さくすることもできません)。

    設定後、SqlConnection con = new SqlConnection(cs); を渡すことで、接続プールに属する接続オブジェクトを取得することができます。

    しかし、接続文字列を変更すると、まったく別のデータベース接続とみなされ、新しい接続プールが作成されるため、システムのオーバーヘッドが増えることになることに注意してください。そのため、特定の接続オブジェクトが接続プールに属していることを確認するためには、大文字小文字、スペースを含め、接続文字列を一切変更してはいけません。   

2. プログラムの変更点

    データベースの一般的な操作

SqlConnection con = new SqlConnection(cs);
    try
    {
       con.Open();
       // Perform various database operations
    }
    catch(Exception ex){ Console.WriteLine(ex.Message); }
    finally
    {
       con.Close();
       con.Dispose();
    }

    この処理は、各操作後に接続オブジェクトが閉じられ、リソースが解放されることを確認する、面倒なものです。最終的に、コネクションプール機能をオンにした後に起こることは、コネクションオブジェクトの状態が実際にクローズに設定され、その後コネクションプールに戻されることです。システムは接続プールに戻すことを知っているので、これを行うためのより良い方法はあるのでしょうか?

using(SqlConnection con = new SqlConnection(cs))
    {
       try
       {
          con.Open();
          // Do Something......
       }
        catch(Exception ex){ Console.WriteLine(ex.Message); }


    }

    Netは名前空間をインポートするだけでなく、プログラム内でローカルにオブジェクトを使用します。上のコードと同様、con のスコープは using に対応する中括弧と同じ大きさだけです。Dispose() はオブジェクト・スコープの最後で自動的に呼び出されてオブジェクトを解放することができるので、上記のコードでは con.Close() と con.Dispose() がなくても、リソースを解放して接続プールに戻すことができ、最終的に手動でクローズする手間を省くことができるのです。しかし、usingはスコープの最後でオブジェクトのDispose()メソッドを自動的に呼び出しているので、すべての種類のオブジェクトがusingによって自動的に解放できるわけではなく、IDisposeインターフェイスを実装しなければならないということにも注意してください。

3. コネクションプールの状態を監視する

    接続プールは、動作状態においてシステムによって完全に制御されていますが、接続プール内の接続オブジェクトの情報をどのように監視すればよいのでしょうか。

    データベースサーバーとデータベースドライバーの2つの方法があります。

    データベースサーバーは、接続オブジェクトの接続先であり、サーバーの状態を問い合わせることで、接続プールのサーバーへのアクセス情報を確認することができる。SQL Server 2005を例にとると、sp_whoまたはsp_who2システムプロシージャを実行すると、データベースにアクセスするすべての接続の一覧を見ることができます。例えば、min pool sizeを5とし、接続プールに少なくとも5つのデータベース・オブジェクトを保持する必要がある場合、プログラム起動後にexec sp_who2を実行すると、データベース内に対応するデータベース名を持つ5つの接続が存在し、操作がなければその状態はスリーピング状態にあることが確認できます。

    一方、データベースの操作にはデータベースドライバーが必要であり、ADO.NETではコネクションプーリングが自動的に管理されるため、データベースドライバーを使用する必要はありません。ドライバの監視は、Windowsの"パフォーマンスカウンタ"の機能に依存します。

    マイコンピュータ(右クリック)--> 管理--> システムツール--> パフォーマンスログとアラート--> カウンターログを右クリックし、新しいログ設定、名前をabc、設定ダイアログボックス表示、 "Add Object" 、ドロップダウンリスト、 " を選択します。.NET Data Provider for SqlServer"を選択し、追加し、閉じます。

    下段はデータのサンプリング間隔、例えば1秒です。Log Files"タブに切り替え、ログファイルの種類を"Text file (comma separated)"に設定すると、ログは"C:/PerfLogs/abc_000001. csv"に記録されますので、OKボタンをクリックしてフォームを閉じてください。

    Counter Logウィンドウに戻り、先ほど設定したabcが緑色で起動していることを確認します。赤色になっている場合は、abcをクリックし、ツールバーの再生ボタン(黒い三角)をクリックすると起動します。

    設定後、プログラムを実行させると、データベース接続プールの状態や接続オブジェクトの数が "C:/PerfLogs/abc_000001.csv" に記録されますので、見たいときにダブルクリックしてエクセルで開くことができます。ファイルは、左側にロギング時間、上側に我々の関心事が表示されます。

    NumberOfPooledConnections: プールに配置された接続の数

    NumberOfActiveConnectionPoolGroups: アクティブなコネクションプールグループの数

    NumberOfInactiveConnectionPoolGroups : 非アクティブなコネクションプールグループの数

    NumberOfActiveConnectionPools : アクティブな接続プールの数

    NumberOfInactiveConnectionPools : 非アクティブなコネクションプールの数

    このログデータを元に、アプリケーションの実行時に接続プールの状態を監視し、そのデータに基づいて接続プールの関連設定を調整することができます。