8

レポート モジュールの一部として、実行時間の長い SQL クエリをいくつか実行しています。これらのクエリは、実行時に動的に構築されます。ユーザーの入力に応じて、それらは単一ステートメントまたは複数ステートメントであり、1 つ以上のパラメーターを持ち、1 つ以上のデータベース テーブルで動作します。つまり、それらの形式は簡単には予測できません。

現在、これらのステートメントを通常の で実行しているだけですSqlConnection

using (SqlConnection cn = new SqlConnection(ConnectionString)) {
    cn.Open();
    // command 1
    // command 2
    // ...
    // command N
}

これらのクエリ (実際にはクエリ バッチ) は実行に時間がかかることがあるため、テーブルのロックが他のユーザーの読み取り/書き込みを妨げていることを懸念しています。これらのレポートのデータがバッチの実行中に変更されても問題ありません。レポート クエリは、それらのテーブルに対する他の操作よりも優先されるべきではなく、テーブルをロックするべきでもありません。

データの変更を伴うほとんどの長時間実行/複数ステートメントの操作では、トランザクションを使用します。ここでの違いは、これらのレポート クエリがデータを変更しないことです。SqlTransaction分離レベルを制御するために、これらのレポート クエリを でラップするのは正しいでしょうか?

すなわち:

using (SqlConnection cn = new SqlConnection(ConnectionString)) {
    cn.Open();

    using (SqlTransaction tr = cn.BeginTransaction(IsolationLevel.ReadUncommitted)) {
        // command 1
        // command 2
        // ...
        // command N

        tr.Commit();
    }
}

これは私の望む結果を達成しますか?データが変更されていない場合でも、トランザクションをコミットすることは正しいですか? 別のアプローチはありますか?

4

2 に答える 2

5

別のアプローチは、接続に対して発行することかもしれません:

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

これは、トランザクションを台無しにすることなく、同じ意図を達成します。または、クエリのテーブルでヒントを使用することもできWITH(NOLOCK)ます。これには、接続をまったく変更しないという利点があります。

重要なことに、(通常は)変更されても(トランザクション、トランザクションスコープ、明示的など)、プールからフェッチするときに、同じ基盤となる接続の使用間で分離レベルがリセットされないことに注意SETてくださいこれは、コードが分離レベルを(直接的または間接的に)変更した場合、新しい接続の分離レベルが何であるかをコードが認識しないことを意味します。

using(var conn = new SqlConnection(connectionString)) {
    conn.Open();
    // isolation level here could be **ANYTHING**; it could be the default
    // if it is a brand new connection, or could be whatever the last
    // connection was when it finished
}

これはWITH(NOLOCK)非常に魅力的です。

于 2012-09-24T07:13:31.200 に答える
1

Marcに同意しますが、代わりに、影響を受けるテーブルでNOLOCKクエリヒントを使用することもできます。これにより、テーブルレベルでテーブルを制御できるようになります。

共有ロックを使用せずにクエリを実行する場合の問題は、「非決定論的」な結果を受け入れることになり、このデータに対してビジネス上の決定を下すべきではないということです。

より良いアプローチは、SNAPSHOTまたはREAD_COMMITED_SNAPSHOT分離レベルのいずれかを調査することです。これらは、ロックをかけることなく、トランザクションの異常に対する保護を提供します。トレードオフは、TempDBに対するIOを増やすことです。これらのレベルのいずれかは、マークが提案したセッションまたは私が提案したテーブルのいずれかに適用できます。

お役に立てれば

于 2012-09-24T07:20:01.617 に答える