79

System.Transactions TransactionScopeを作成するときに、デフォルトの Isolationlevel としてSerializable を使用する正当な理由が何であるかを考えているだけです。あなたのコード) web/app.config

using(var transaction = TransactionScope()) 
{
    ... //creates a Transaction with Serializable Level
}

代わりに、次のようなボイラープレート コードを常に記述する必要があります。

var txOptions = new System.Transactions.TransactionOptions();
txOptions.IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted;

using(var transaction = new TransactionScope(TransactionScopeOption.Required, txOptions)) 
{
    ...
}

何か案は?

4

3 に答える 3

95

実際Serializableのところ、デフォルトは、.NET がリリースされていなかった時代 (1999 年以前)、DTC (分散トランザクション コーディネーター) プログラミングから来ています。

DTC は、ネイティブのISOLATIONLEVEL列挙を使用します。

ISOLATIONLEVEL_SERIALIZABLE 現在のトランザクションによって読み取られたデータは、現在のトランザクションが終了するまで、別のトランザクションによって変更できません。現在のトランザクションに影響を与える新しいデータを挿入することはできません。これは最も安全な分離レベルであり、デフォルトですが、最低レベルの同時実行が許可されます。

.NETTransactionScopeは、これらのテクノロジの上に構築されています。

さて、次の質問は、なぜ DTCISOLATIONLEVEL_SERIALIZABLEが既定のトランザクション レベルとして定義するのかということです。DTC が 1995 年頃 (確かに 1999 年より前) に設計されたためだと思います。当時、SQL 標準は SQL-92 (または SQL2) でした。

SQL-92 によるトランザクション レベルの説明は次のとおりです。

SQL トランザクションには、READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ、または SERIALIZABLE の分離レベルがあります。SQL トランザクションの分離レベルは、その SQL トランザクション内の SQL データまたはスキーマに対する操作が、同時 SQL トランザクション内の SQL データまたはスキーマに対する操作の影響を受け、影響を与える可能性の程度を定義します。SQL トランザクションの分離レベルは、デフォルトで SERIALIZABLE です。レベルは、 によって明示的に設定できます<set transaction statement>

分離レベル SERIALIZABLE での同時 SQL トランザクションの実行は、シリアライズ可能であることが保証されています。シリアル化可能な実行は、同じ SQL トランザクションのシリアル実行と同じ効果を生み出す、SQL トランザクションを同時に実行する操作の実行であると定義されます。逐次実行とは、次の SQL トランザクションが開始される前に、各 SQL トランザクションが完了するまで実行される実行です。

于 2014-04-28T14:14:31.013 に答える
52

定型コードの記述を減らす便利な方法は、次のようにビルダー クラスでラップすることです。

public static class TransactionScopeBuilder
{
    /// <summary>
    /// Creates a transactionscope with ReadCommitted Isolation, the same level as sql server
    /// </summary>
    /// <returns>A transaction scope</returns>
    public static TransactionScope CreateReadCommitted()
    {
        var options = new TransactionOptions
        {
            IsolationLevel = IsolationLevel.ReadCommitted,
            Timeout = TransactionManager.DefaultTimeout
        };

        return new TransactionScope(TransactionScopeOption.Required, options);
    } 
}

次に、トランザクション スコープを作成するときに、次のように使用できます。

using (var scope = TransactionScopeBuilder.CreateReadCommitted())
{
    //do work here
}

必要に応じて、その他の一般的なトランザクション スコープのデフォルトをビルダー クラスに追加できます。

于 2013-03-07T01:45:02.167 に答える
29

まあ、これは「デザイナーだけが確実に知っている」タイプの質問の 1 つだと思います。とにかく、ここに私の2セントがあります:

Serializable は最も「制限的な」分離レベル (ロックベースの RDBMS でのロック、したがって同時アクセス、デッドロックなどに関して) ですが、最も「安全な」分離レベルでもあります (データの一貫性に関して)。

したがって、あなたのようなシナリオでは追加の作業が必要になりますが (それが行われました ;-)、デフォルトで最も安全なバリアントを選択することは理にかなっています。SQL Server (T/SQL) はREAD COMMITTEDを使用することを選択し、明らかに他の理由を適用します:-)

構成によって変更可能にすることは、悪い考えです。構成をいじることによって、完全に機能するアプリケーションを壊れたアプリケーションにレンダリングする可能性があるためです (他のアプリケーションと連携するように設計されていない可能性があるため)。または、議論を好転させるために、分離レベルを「ハードコーディング」することで、アプリケーションが期待どおりに動作することを確認できます。ほぼ間違いなく、分離レベルは構成オプションに適していません (トランザクション タイムアウトは実際には適しています)。

于 2012-07-02T11:48:46.350 に答える