5

刚刚阅读了 Omar 在他的博客 Linq to SQL 上的这篇有趣的文章,使用未提交的读取来解决事务死锁和查询超时问题,最后 Javed Hasan 开始与他争论他对大容量站点上无锁情况的解决方案。

这里要解决的问题是,从 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 这样的高容量网站上对这个特定问题做了什么,或者 Jeff 和他们的人在这方面做了什么?

编辑:阅读第一篇文章后,我想在 Omar 的文章中指出一些事情。

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

4 回答 4

9

首先请避免未提交的读取,它们会导致很多问题。一个更好的方法是将数据库设置为快照隔离这就是杰夫所做的。

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

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

Javed 方法会更好,因为在处置时 MS 有机会清理连接上的东西。

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

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

  • 持有一堆当前交易
  • 提交事务时确认您在创建者线程上
  • 在 dispose 时将事务隔离重置为之前的状态
  • 如果事务未提交,则在处置时回滚。
  • 支持嵌套回滚。
于 2009-03-09T21:08:20.427 回答
5

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

如果确实选择使用未提交的读取,我在 C# 中使用扩展方法写了一个方便的解决方案。

于 2010-07-30T06:56:15.457 回答
1

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

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

于 2009-07-30T20:37:47.047 回答
0

关于 .Net 中的事务和 DTC 的(有点令人惊讶的)副作用,Juval Lowy 的这篇文档介绍了 .NET Framework 2.0 中的 System.Transactions很好地解释了事情并且仍然完全有效(.Net4)。值得一读。(我也会发表评论......如果可以的话。)

于 2011-04-20T09:22:23.997 回答