SqlTransaction を使用して数千の SqlCommand を処理するとメモリ例外が発生する
-
12-12-2019 - |
質問
SQL Server 2008 Express データベースを使用して、標準の C# Windows フォーム アプリでカスタム レプリケーション関数を作成しました。これは基本的に、サブスクライバ データベースに対して実行する必要がある一連の SQL ステートメントをプルダウンします。完全なリフレッシュでは、実行する必要のある最大 200,000 個以上のステートメントが実行される可能性があります。
以下に示すように、コード ブロック内でこれらのステートメントを処理します。
using (SqlConnection connection = ConnectionManager.GetConnection())
{
connection.Open();
SqlTransaction transaction = connection.BeginTransaction();
// Process 200k+ Insert/Update/Delete statements using SqlCommands
transaction.Commit
}
私が発見したのは、アプリケーションのメモリ使用量は、最初の 30,000 ステートメントで約 40 MB でかなり安定しているということです。その後、突然約 300MB に跳ね上がったように見え、その後 OutOfMemory 例外が発生するまで増加します。
私が使用している方法は可能でしょうか。単一のトランザクション内でこれほど多くのステートメントを処理できますか?これはできるはずだと思います。もっと良い方法があれば、ぜひここに載せたいと思います。これをトランザクション対応にする必要があります。そうしないと、部分的なレプリケーションが発生してデータベースが壊れてしまいます。
ありがとう。
編集:
コンピューターを再起動した後、200k 以上の完全なレプリケーションを実行することができました。レプリケーションが完了した後、ある時点でメモリ使用量が 1.4 GB まで増加しましたが、メモリ使用量は 40 MB まで下がりました。このことから、コマンドを処理するループ内の何かがメモリの増大を引き起こしている可能性があると結論付けています。
解決
あなたは Disposing
フォームと使い捨てコントロールを閉じる前に?
すべての Disposable オブジェクトを using ステートメントでラップします。詳細についてはここをクリックしてください
接続を何度も開いたり閉じたりせず、単一のトランザクションでデータをデータベースに送信します。詳細についてはここをクリックしてください
それでもアプリケーションが大量のメモリを保持している場合は、Red Gate Ants Memory Profiler のような Doctor が必要です。詳細を確認するにはここをクリックしてください
単一のトランザクション内でそれほど多くのステートメントを処理できますか?
これを行うには以下のオプションがあります...
- レコードを一括挿入して操作します
Stored Proc
. - 準備する
XML
そして文字列を送信してくださいDatabase
. - 読み取り専用で送信します
DataTable
ストアドプロシージャを介した SQL Server 内
サンプルストアドプロシージャ
Begin Try
Set NoCount ON
Set XACT_Abort ON
Begin TRan
--Your queries
Commit Tran
Begin Tran
Begin Catch
Rollback Tran
End Catch
必ず Dispose
一度使用されなくなったオブジェクト。
このようにあるべきです
using (SqlConnection connection = new SqlConnection())
{
connection.Open();
using (SqlTransaction transaction = connection.BeginTransaction())
{
transaction.Commit();
}
}
確認しましたか SqlCommand
また?
using (SqlCommand cmd = new SqlCommand())
{
}