sql-server - 使用 ADO.NET TransactionScope 与 NOLOCK 上的 ExecuteCommand 的高容量站点,直接读取未提交的内容?

标签 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,否则在数据库中的高容量行将被锁定并导致错误。 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 事务方式,甚至尝试了 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/

相关文章:

hibernate - "Transaction in view"与 Hibernate、Spring、Struts

sql-server - 如何将 SQL getdate() 函数转换为 dd/mm/yyyy 格式的字符串?

sql - 从表中删除孤儿

sql - 将计算值存储在数据库中是个坏主意吗?

c# - 为什么 LINQ to SQL 将 GroupBy 翻译成多个查询

LINQ 查询检查是否为空

.net - EF4、事务范围和任务<>

sql - FROM 内的WITH 的替代方案

vb.net - 如何使用VB.Net Lambda表达式按多列排序

c# - 如何在 C# 中将 TranscactionScope 限制为给定的 DataBaseContext?