2

@usrと私は、 .NET がアイドル状態の開いている接続を清掃するかどうかについて、別の質問で意見の相違がありますが、保持された参照は維持されます。

ドキュメントに基づいてSQLConnection、物理接続が一定期間アイドル状態である場合、オブジェクト参照が保持されたままであっても、一定期間後に再利用されると主張しています。

usr は、これは起こらないと主張しており、参照がなくなった接続のみを回収します。これは接続プーリングの信頼性を低下させ、トランザクションに大混乱を引き起こすという彼の主張です。

認めますが、文書は保持された参照の問題について曖昧です。

推測だけでなく、これに関する信頼できる回答を探しています。いずれかのケースを実験して証明した人か、内部の仕組みを知っている人です。

それで、それはどれですか?

編集:

ここでの混乱は、「クローズド」という用語にあると思います。事実と思われるのは、ドキュメントが物理接続を閉じることをプールからの接続の「削除」と呼んでいることです。「閉じる」とは、開いている物理接続を解放してプールに戻し、再利用することを指します。

開いている接続を中止することはできますが、クライアント アプリによってまだ開かれている場合、プーラーがこれを無効としてマークするかどうかは不明です (つまり、クライアント アプリは、中止された接続でまだ close を呼び出していません)。プール数の一部として。

4

3 に答える 3

2

解放されるまで、接続がプールに戻らないことは 100% 確実です。セッションで一時テーブルを作成し、ユーザーの入力を待っている間、ハングしたままにしました。ユーザーは 6 分後に戻ってきてボタンを押すと、同じSPIDで続行され、一時テーブルに対して処理が続行されます。

ロジックを適用すると、X 分間アイドル状態だったという理由だけで SPID を失った場合の大混乱を想像できるので、理にかなっています。SQL Server を存続させるためだけに、コマンドを使用して SQL Server に "ping" を実行し続ける必要がありますか? (それは非常識だろう)


あなたは2つの概念を混同しているようです。接続が閉じられると、プールに戻ります。範囲外になると、暗黙的に閉じられます -> プールに戻ります。「アイドル」への参照は、プール内の接続がアクティブに参照されて閉じられていないときではなく、アイドル状態になったときを指します。保持された接続は、どのような種類の清掃にも適格になるプール内にさえありません。プールからリソースを解放することは理にかなっています。Web アプリは簡単に数百の接続にバーストでき、その後数か月間は約 20 程度のアクティブな同時接続を維持できるからです。

于 2012-09-30T19:45:37.783 に答える
1

.NET がアイドル状態の開いている接続を清掃するが、保持された参照を維持するかどうか

ここでは「保持された参照」は重要ではありません。ポイントは「オープン」です。接続を適切にリサイクルするには、Dispose()またはClose()それを行う必要があります。

于 2012-09-30T19:49:19.883 に答える
0

次のプログラムを実行しました。

        var conn = new SqlConnection("...");
        conn.Open();
        conn.ExecuteNonQuery("select null");
        Thread.Sleep(TimeSpan.FromMinutes(11));
        conn.ExecuteNonQuery("select null");

正常に実行されました(カスタムヘルパーメソッドを使用しているため、直接実行できません)。

もちろん、これは何も証明しません (正しく実行されなかった場合のみ)。Reflector は、プールが 6.5 分後に初めてクリーンアップされ、その後は 30 秒ごとにクリーンアップされることを示しています。

private Timer CreatePruningTimer()
{
    return new Timer(new TimerCallback(this.PruneConnectionPoolGroups), null, 240000, 30000);
}

したがって、テストによって問題が明らかになったはずです。

現在、ドキュメントの文は特に明確ではありません。GC やオブジェクト参照についても言及していません (あなたの質問ではそう言っていますが、そうではありません)。

接続プーラーは定期的に接続プールをスキャンして、Close または Dispose によって閉じられなかった未使用の接続を探し、見つかった接続を回収します。アプリケーションが接続を明示的に閉じたり破棄したりしない場合、接続プーラーがそれらを再利用するのにかなりの時間がかかる可能性があるため、接続で明示的に Close と Dispose を呼び出すことを確認することをお勧めします。

私はそれを信頼していません。ベイジアンの用語で言えば、Microsoft のドキュメントは強力な証拠ですが、強力な反証があれば、反対の結論に達する可能性があります。

開いている接続が理由なく閉じられないという次の証拠があります。

  1. これにより、防止できないランダムな障害が発生します (再試行のみ)。
  2. 問題ないトランザクションを中止します
  3. 長時間のトランザクションが不可能になる
  4. この動作が当てはまる理由がわかりません
  5. ドキュメント内の文は、次のように解釈できます。プールは、閉じられていないが、対応する SqlConnection オブジェクトが GC されている接続を定期的に返します (WeakReference などを使用して検出します)。Microsoft のドキュメント ライターは、この問題を意図していたか、理解していなかったと思います (もっともらしい!)
  6. テストは問題を示しませんでした
  7. SSMS はどのようにして 1 時間のクエリを実行することができますか? SSMS も同じ制限を受ける必要があります
于 2012-09-30T19:47:34.750 に答える