为什么是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 TransactionScope
build立在这些技术之上。
现在,下一个问题是:为什么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选项( 事务超时的确如此)。