交易发生时是否可以选择数据?

时间:2009-12-17 00:47:54

标签: sql-server linq-to-sql transactions

我正在使用transactionscope来确保正确地将数据读入数据库。但是,我可能需要在事务运行时选择一些数据(来自另一个页面)。可以这样做吗?在数据库方面,我非常棒。

我正在使用LinqToSQL和SQL Server 2005(dev)/ 2008(prod)。

3 个答案:

答案 0 :(得分:1)

是的,在事务运行时仍可以从数据库中选择数据。

通常可以从其他事务中读取不受事务影响的数据(例如,表中未更新的行)。 (在某些情况下,SQL Server将引入一个表锁,它会停止对表中所有行的读取,但它们不常见,并且通常是查询或服务器上发生其他事情的症状)。

您需要查看Transaction Isolation Levels,因为它们可以准确控制此行为的工作方式。

以下是设置事务范围隔离级别的C#代码。

TransactionOptions option = new TransactionOptions();        
options.IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted;        
using (TransactionScope sc = new TransactionScope(TransactionScopeOption.Required, options)
{
    // Code within transaction
}

通常,根据事务中指定的事务隔离级别(或任何表提示,如NOLOCK),您将获得不同级别的数据锁定,以保护应用程序的其余部分免受事务中的活动影响。例如,事务隔离级别为READUNCOMMITTED,您可以在事务发生时查看该事务中的写入。这允许脏读,但也防止(大多数)数据锁。

比例的另一端是SERIALIZABLE之类的隔离级别,可确保您的交易活动完全隔离,直到它已经完成。

答案 1 :(得分:0)

是的,默认情况下,TransactionScope将锁定事务中涉及的表。如果您需要在进行交易时阅读,请使用TransactionScope TransactionOptions输入另一个IsolationLevel.ReadUncommitted

TransactionScopeOptions = new TransactionScopeOptions();
options.IsolationLevel = IsolationLevel.ReadUncommitted;
using(var scope = new TransactionScope(
    TransactionScopeOption.RequiresNew, 
    options
) {
    // read the database
}

使用LINQ-to-SQL DataContext

// db is DataContext
db.Transaction = 
    db.Connection.BeginTransaction(System.Data.IsolationLevel.ReadUncommitted);

请注意System.Transactions.IsolationLevelSystem.Data.IsolationLevel之间存在差异。是的,你读得正确。

答案 2 :(得分:0)

对于已提供的建议,我强烈建议您研究快照隔离模型。在Using Snapshot Isolation进行了很好的讨论。在数据库上启用Read Committed Snapshot ON可以缓解许多争用问题,因为读者不再被编写者阻止。由于默认读取是在读取提交隔离模式下执行的,因此这个简单的数据库选项开关具有直接的好处,并且不需要更改应用程序。

没有免费的午餐,所以这是有代价的,在这种情况下,价格是对tempdb的附加负载,请参阅Row Versioning Resource Usage

如果您使用的是explict隔离级别,特别是如果您使用默认的TransactionScope Serializable模式,那么您必须检查您的代码以强制执行更多的ReadCommited隔离级别。如果您不知道您使用的隔离级别,则表示您使用ReadCommited。