10

i SqlConnectionオブジェクトを破棄しますが、もちろん実際には閉じていません。データベース オブジェクトのロックを保持しないようにするには、接続を閉じる必要があります。閉じた接続がロックを保持しないようにするにはどうすればよいですか?


知らない人のための上記の文の説明:

  • ADO または ADO.NET 接続を閉じても、実際には SQL Server への接続が切断されているわけではありません。ADO/ADO.NET インフラストラクチャは、再度使用したい場合に備えて接続を維持します。接続は、「接続プール」と呼ばれるものに残ります。

  • 数分間使用されないと、接続は実際に閉じられます。しかし、そうではありません。TCP/IP には、TCP 接続をさらに数分間 (「CLOSE_WAIT」状態で) 開いたままにする独自の方法があります。これは、同じ IP:Port への TCP 接続を再度開くように要求した場合に行われます。その場合、すでに開いている TCP 接続を使用できます。

  • 接続プールと SQL Server を使用すると、SQL Server への接続が確立されたままになります。各接続には、それが置かれているデータベース コンテキストがあります。接続がそのデータベースに置かれている限り、接続はそのデータベースの共有データベース (S-DB) ロックを保持します。

  • 共有データベース ロックは、単に「私がいる間はこのデータベースを削除しないでください」という意味です。

接続プールの利点を維持しながら、データベースで共有ロックを保持しないようにするにはどうすればよいですか?


現在の私のアドホックな解決策は、開発者が Dispose を呼び出すたびに:

connection.Dispose()

これをグローバル ヘルパー関数の呼び出しに変更します。

Database.DisposeConnection(connection);

これにより、データベース コンテキストがmasterに変更されます。

public static void DisposeConnection(SqlConnection connection)
{
    //Stop holding a database lock - in my database at least
    ADOHelper.ExecuteNonQuery(connection, "USE master");

    connection.Dispose();
}

それは私の差し迫った問題を解決します。閉じた接続がデータベースのロックを保持していません。

しかし今、私は接続プーリングが頭脳を混乱させるのではないかと心配しています.


誰かが知らなかった場合、または別の方法で考えた場合:

SDKから:

CloseDisposeは機能的に同等です。

4

5 に答える 5

7

データベースを復元するために、データベースをシングル ユーザー モードにすることができます。IIRC、このようなもの...

ALTER DATABASE TheDatabaseToRestore SET SINGLE_USER WITH  ROLLBACK IMMEDIATE;
RESTORE DATABASE TheDatabaseToRestore 
FROM DISK =N'Z:\Path\To\Backup\BackupFile';
ALTER DATABASE TheDatabaseToRestore SET MULTI_USER;

詳細については、 SQL Server を復元するための排他的アクセス権の取得、またはSQL を使用してデータベース バックアップを復元するを参照してください。

編集: シングルユーザーモードは、バックアップと復元を目的としています(非高速版では、これを定期的に使用しています)。これを使用すると、他のすべての接続が無効になり、新しい接続を作成できなくなります。「ROLLBACK IMMEDIATE」などのさまざまな「WITH」オプションを試したことはありませんが、その使い方は簡単なようです。

于 2009-08-29T11:11:06.303 に答える
3

SqlClient.ClearPoolを試しましたか?

MSDN から:

ClearPool は、接続に関連付けられている接続プールをクリアします。接続に関連付けられた追加の接続が呼び出し時に使用されている場合、それらは適切にマークされ、それらに対して Close が呼び出されたときに (プールに返される代わりに) 破棄されます。

すべての接続で ClearPool を呼び出すだけですが、これを行うとプーリングの利点が失われます。

public class DataFactory
{
  public SqlConnection CreateConnection(string connString)
  {
    SqlConnection conn = new SqlConnection(connString);
    SqlClient.ClearPool(conn);
    return conn;
   }
}

または、接続文字列の Pooling プロパティを使用して、プーリングをすべて無効にすることもできます。

string connString = "Data Source=MYSERVER;Initial Catalog=myDb;Integrated Security=true;Pooling=false"
于 2009-08-28T17:30:25.633 に答える
1

「USETempDB;」を実行します。最初。次に、それを閉じます。

または、それがあなたの好みに合っている場合は、「USEmaster;」。

これらのデータベースのいずれかに対するS-DBロックは、通常の運用操作では問題になりません。どちらか一方を削除して、サーバーの実行を続行することはできないためです。

于 2009-08-31T18:23:05.397 に答える
1

あなたが言うように、あなたが接続を閉じるか破棄するとき、それはプールに戻りますが、実際には閉じられていません。

次に、プール内のすべての接続を閉じるために行う必要があること。これは、ClearAllPoolsコマンドを使用して実行できます。

ClearAllPoolsは、接続プールをリセット(または空)します。呼び出し時に使用中の接続がある場合、それらは適切にマークされ、Closeが呼び出されたときに(プールに戻されるのではなく)破棄されます。

http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection.clearallpools(VS.80).aspx

同じことを行うが、単一の接続用のClearPoolコマンドもあります。

お役に立てれば

シラーズ

于 2009-08-29T07:33:09.110 に答える
0

コメントを読んで、あなたはそれを復元したいと思います。

OK、オフラインにします。

復元はアプリが行うべきことではないため、DBAは復元の前にこれを実行します。

ALTER DATABASE foo SET OFFLINE WITH ROLLBACK IMMEDIATE
于 2009-02-07T18:14:10.680 に答える