在NOLOCK上使用ADO.NET TransactionScope vs ExecuteCommand的高容量站点,直接READ UNCOMMITTED?

时间:2009-03-09 20:54:18

标签: sql-server linq-to-sql transactionscope nolock read-uncommitted

请阅读Omar在他的博客Linq to SQL solve Transaction deadlock and Query timeout problem using uncommitted reads 和最后的这篇有趣的文章 Javed Hasan开始与他讨论他在高容量网站上解决nolock情况的问题。

这里,试图解决的问题是,从sql意义上讲,我们需要使用带有NOLOCK的Select语句或使用SET TRANSACTION LEVEL READ UNCOMMITTED,否则DB中的高容量行将被锁定并导致错误。 Omar使用的技术是Linq2Sql,所以问题是我们如何在你的C#数据访问代码中实现这一点,所以上述情况不会发生?

基本上在帖子中,Omar通过在现实世界网站上使用SqlProfiler等工具进行工作和测试来解决他的问题,而Javed Hasan则使用MSDN文档和Scott Hanselman的博客文章等来解决他的问题。

奥马尔建议使用以下

using (var db = new DropthingsDataContext2())
{
  db.Connection.Open();
  db.ExecuteCommand("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;");

  var user = db.aspnet_Users.First();
  var pages = user.Pages.ToList();
}

而Javed Hasan建议

using (new TransactionScope(TransactionScopeOption.Required, 
  new TransactionOptions { IsolationLevel = IsolationLevel.ReadUncommitted }))
{
 //Your db Operation
}

我很有兴趣知道你们在这个特定问题上对你们这些特殊问题做了什么,比如StatckOverflow,或杰夫和他们的家伙在这方面做了什么?

编辑:在阅读完第一篇文章后,我想在奥马尔的帖子中指出一些内容。

  1. 他的方法确实遇到了连接问题,但是他解决了,看到了他的帖子。
  2. 更重要的是,他提到他尝试使用ADO.NET Transaction方式,甚至尝试了Scott Hanselman在他的博客上写的内容,但它不适用于高容量网站,它会降低性能。 Omar说这个“System.Transactions有很大的开销。我从来没有能够在高容量网站上使用它而不会使CPU达到100%而Req / sec降到1/10。它是为企业应用程序而不是高卷网站。“

4 个答案:

答案 0 :(得分:9)

首先请避免未提交的读取,它们可能会导致很多问题。更好的方法是将数据库设置为snapshot isolation这就是Jeff所做的

Jeff基本上说:“bla bla bla,be real,bla bla bla,数据库理论家,bla bla bla,READ UNCOMMITTED对于不需要数据一致性的REAL生产应用程序非常有用。” Jeff不是DBA,幸运的是,SO上有很多DBA。

Omar方法的问题在于它可能会将“读取未提交”隔离级别的连接泄漏到您的连接池中,这可能会对您的网站造成严重破坏。含义随机语句可以在未提交的读取中执行。

Javed方法会好得多,因为在部署MS上有机会清理连接上的东西。

编辑如果您遇到Javed方法的性能问题,可以考虑滚动自己的事务管理器。

您可能想要做的一些事情:

  • 保留一堆当前交易
  • 确认您在提交交易时在创建者线程上
  • 将事务隔离重置为dispose上的先前状态
  • 如果未提交交易,则回滚处理。
  • 支持嵌套回滚。

答案 1 :(得分:5)

我是Microsoft的SQL Server组中的工具团队的开发人员。许多应用程序对事务一致性不是非常敏感,特别是如果您编写的应用程序执行报告或偶尔会出现不一致的数据并不是世界末日。当然,如果您编写的财务应用程序或其他对数据不一致性容忍度很低的内容,您可能希望探索其他解决方案。

如果确实选择使用未提交的读取,我在C#中使用扩展方法blogged a handy solution

答案 2 :(得分:1)

{我的(差)声誉阻止我发表评论,所以我把它作为答案}

如果您通过System.Transactions使用IsolationLevel并在事务块中创建新的Linq上下文,SQL Server最终会尝试调​​用DTC来协调事务。这恰好发生在我身上,非常意外。

答案 3 :(得分:0)

关于.Net中的交易和DTC的(某种程度上令人惊讶的)副作用,Juval Lowy撰写的这份文件Introducing System.Transactions in the .NET Framework 2.0解释得非常好并且仍然完全有效(.Net4)。值得阅读。 (如果可以的话,我也会发表评论。)