刚刚阅读 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,否则在数据库中的高容量行将被锁定并导致错误。 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 事务方式,甚至尝试了 Scott Hanselman 在他的博客上写的内容,但它不适用于高容量网站,它会大大降低性能。 Omar 表示,“System.Transactions 的开销很大。我从来没有能够在不使 CPU 达到 100% 且请求/秒下降到 1/10 的情况下在大容量网站上使用它。它是为企业应用程序而设计的,而不是为高性能应用程序而设计的。”批量网站。”
最佳答案
首先请避免未提交的读取,它们可能会导致很多问题。更好的方法是将数据库设置为 snapshot isolation 。 这就是杰夫所做的。
Jeff 基本上是说:“bla bla bla,说实话,bla bla bla,数据库理论家,bla bla bla,READ UNCOMMITTED 对于不需要数据一致性的真实生产应用程序很有用。” Jeff 不是 DBA,幸运的是这里有很多 DBA。Omar 方法的问题在于,它可能会将“读未提交”隔离级别的连接泄漏到您的连接池中,这可能会对您的网站造成严重破坏。这意味着随机语句可以在未提交的读中执行。
Javed 方法会更好,因为在处置时 MS 有机会清理连接上的东西。
编辑如果您在使用 Javed 的方法时遇到性能问题,您可以考虑滚动自己的事务管理器。
您可能想做的一些事情:
- 保存当前交易的堆栈
- 提交事务时确认您位于创建者线程
- 在处置时将事务隔离重置为其之前的状态
- 如果事务未提交,则回滚处置。
- 支持嵌套回滚。
关于sql-server - 使用 ADO.NET TransactionScope 与 NOLOCK 上的 ExecuteCommand 的高容量站点,直接读取未提交的内容?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/628004/