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