为什么是System.Transactions TransactionScope默认Isolationlevel可串行化

我只是想知道什么是一个很好的理由,使用Serializable作为默认的Isolationlevel可能是创build一个System.Transactions TransactionScope时 ,因为我想不出任何(似乎你不能通过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)) { ... // } 

有任何想法吗?

事实上, Serializable是默认情况下,.NET从DTC( 分布式事务处理协调器 )编程开始还没有发布(1999年之前)。

DTC使用本地ISOLATIONLEVEL枚举:

ISOLATIONLEVEL_SERIALIZABLE在当前事务完成之前,当前事务读取的数据不能被另一个事务更改。 不会插入会影响当前事务的新数据。 这是最安全的隔离级别,是默认级别,但允许最低级别的并发。

.NET TransactionScopebuild立在这些技术之上。

现在,下一个问题是:为什么DTC将ISOLATIONLEVEL_SERIALIZABLE定义为默认事务级别? 我想这是因为DTC是在1995年左右(当然是在1999年之前)devise的。 那时,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事务开始之前执行完成。

减less写样板代码的一个有用的方法是将其包装在构build器类中,如下所示:

  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); } } 

那么你可以在创build事务范围时像这样使用它:

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

您可以根据需要将其他常见事务作用域默认值添加到构build器类。

那么,我想这是“只有devise师肯定会知道”types的问题之一。 但是这里是我的两分钱:

虽然Serializable是最“限制”的隔离级别(关于locking,在基于锁的RDBMS中,因此并发访问,死锁等),但它也是最“安全”的隔离级别(涉及数据的一致性)。

所以,当你需要额外的工作时(比如你已经完成了这个工作),默认情况下select最安全的变体是很有意义的。 SQL Server(T / SQL)select使用READ COMMITTED ,显然是应用其他原因:-)

如果通过configuration来改变它,那么将会是一个糟糕的主意,因为通过摆弄configuration,你可以把一个完美的应用程序渲染成一个破碎的应用程序(因为它可能根本不能用于其他任何devise)。 或者通过“硬编码”隔离级别来解决争论,可以确保应用程序按预期工作。 可以说,隔离级别不适合configuration选项( 事务超时的确如此)。