我只是想知道在创建System.Transactions TransactionScope 时,使用Serializable 作为默认的Isolationlevel是一个很好的原因,因为我想不出任何(似乎您无法通过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))
{
...
}
有什么想法吗?
答案 0 :(得分:81)
事实Serializable
是默认来自.NET甚至没有发布(1999年之前),来自DTC(Distributed Transaction Coordinator)编程。
DTC使用原生ISOLATIONLEVEL枚举:
<强> ISOLATIONLEVEL_SERIALIZABLE 强> 当前事务读取的数据不能 在当前交易之前被另一笔交易更改 饰面。不能插入会影响当前的新数据 交易。 这是最安全的隔离级别,是默认值, 但允许最低级别的并发。
.NET TransactionScope
建立在这些技术之上。
现在,下一个问题是:为什么DTC将ISOLATIONLEVEL_SERIALIZABLE
定义为默认事务级别?我想这是因为DTC是在1995年左右设计的(肯定在1999年之前)。那时,SQL Standard是SQL-92(或SQL2)。
以下是SQL-92关于交易级别的说法:
SQL事务的隔离级别为READ UNCOMMITTED, READ COMMITTED,REPEATABLE READ或SERIALIZABLE。隔离级别 SQL事务的定义了操作的程度 SQL事务中的SQL数据或模式受到 影响和影响对SQL数据或模式的操作 并发SQL事务。 SQL事务的隔离级别 默认为SERIALIZABLE 。级别可以由。明确设置
<set transaction statement>
。在隔离级别执行并发SQL事务 SERIALIZABLE保证可序列化。可序列化的exe- cution被定义为执行同意的操作 正在执行产生与之相同效果的SQL事务 一些串行执行那些相同的SQL事务。连续执行 cution是每个SQL事务执行完成的一个 在下一个SQL事务开始之前。
答案 1 :(得分:46)
减少编写样板代码的一种有用方法是将它包装在类似的构建器类中:
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
}
您可以根据需要将其他常见事务范围默认值添加到构建器类。
答案 2 :(得分:27)
嗯,我想这是“只有设计师肯定会知道”类型的问题之一。但无论如何,这是我的两分钱:
虽然Serializable是最“限制”的隔离级别(关于锁定,基于锁的RDBMS,因此是并发访问,死锁等),但它也是最“安全”的隔离级别(关于数据的一致性)
因此,虽然在像你这样的场景中需要额外的工作(在那里做了;-),默认情况下选择最安全的变体是有意义的。 SQL Server(T / SQL)选择使用READ COMMITTED,显然应用其他原因: - )
通过配置使其可更改将是一个坏主意,因为通过摆弄配置,您可以将完美的应用程序呈现给损坏的应用程序(因为它可能根本不适用于其他任何东西)。或者通过“硬编码”隔离级别来改变参数,可以确保应用程序按预期工作。可以说,隔离级别不适合配置选项(而transaction timeout确实是这样)。