2012-07-02 43 views
54

我只是想知道有什麼好理由使用序列化作爲默認創建的System.Transactions的時候的TransactionScope的IsolationLevel可能是,因爲我想不出任何(與看來,你不能改變通過web/app.config中的默認,所以你總是必須設置它在你的代碼)爲什麼System.Transactions的TransactionScope的默認的IsolationLevel Serializable接口

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)) { 
    ... // 
} 

任何想法?

+1

將樣板代碼移到輔助方法中,這個問題再也不會打擾您。 – usr

回答

68

事實上,Serializable是默認來自.NET甚至沒有從DTC(Distributed Transaction Coordinator)編程中發佈(1999年之前)的時間。

DTC採用的是原生ISOLATIONLEVEL枚舉:

ISOLATIONLEVEL_SERIALIZABLE 數據由當前事務讀取不能 被另一個事務改變,直到當前事務 結束。不會插入影響當前 交易的新數據。 這是最安全的隔離級別,是默認級別, 但允許最低級別的併發。

.NET TransactionScope建立在這些技術之上。

現在,下一個問題是:爲什麼DTC將ISOLATIONLEVEL_SERIALIZABLE定義爲默認交易級別?我想這是因爲DTC是在1995年左右(肯定是在1999年之前)設計的。那時,SQL標準是SQL-92(或SQL2)。

這裏是什麼SQL-92說,關於事務級別:

的SQL事務都有所讀取未提交的隔離級別, 提交讀,可重複讀取,或SERIALIZABLE。 SQL事務的隔離級別 定義了SQL事務中的SQL數據或模式上的操作受 效應影響並且可能影響對 併發中的SQL數據或模式的操作的程度SQL-交易。 默認情況下,SQL事務 的隔離級別爲SERIALIZABLE。級別可以通過 <set transaction statement>明確設置。

在隔離級別執行併發SQL事務 SERIALIZABLE保證是可序列化的。可序列化的exe文件被定義爲執行併發執行的SQL操作,這些操作產生與那些相同SQL事務的一些串行執行相同的效果。一系列exe文件是其中每個SQL事務在下一個SQL事務開始之前執行完成 的文件。

+2

感謝這個非常有趣和信息豐富的答案。 –

25

那麼,我想這是「只有設計師肯定會知道」類型的問題之一。但是這裏是我的兩分錢無論如何:

雖然可序列化是最「限制」的隔離級別(關於鎖定,在基於鎖的RDBMS,因此併發訪問,死鎖等),它也是最「安全「隔離級別(關於數據的一致性)。

因此,雖然需要額外的工作在像你這樣的場景中(在那裏做過;-),所以默認選擇最安全的變體是有意義的。 SQL Server(T/SQL)選擇使用READ COMMITTED,顯然是運用其他原因:-)

通過配置使其可變,將是一個糟糕的主意,因爲通過擺弄配置,您可以將完美的工作應用程序呈現給破壞了一個(因爲它可能根本不是設計用於其他任何事情)。或者通過「硬編碼」隔離級別來解決爭論,可以確保應用程序按預期工作。可以說,隔離級別不適合配置選項(雖然確實是transaction timeout)。

+2

「你可以將一個完美的工作應用程序渲染成一個破碎的應用程序」+1 – Steven

+2

請注意,即使可序列化的隔離級別仍不能保證不會出現貨幣問題。 – Steven

+1

@Steven:確實。因此,我使用的措辭「_most_安全」;-) –

40

削減編寫樣板代碼一個有用的方法是將它包裝在一個生成器類,像這樣:創建一個事務範圍時

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 
    } 

您可以根據需要將其他常見事務作用域默認值添加到構建器類。

+1

這實際上是我做了一箇中央位置,在那裏爲我的用戶獲得「默認」事務處理範圍 –

相關問題