2012-01-09 51 views
5

我正在使用多线程应用程序(C#),并且2个线程同时使用NOLOCK更新表,这是一个问题吗?更具体地说,他们都在更新相同的记录。NOLOCK与多线程

+3

知道何时使用NOLOCK需要深入了解SQL Server如何,何时以及为何锁定了什么。它不应该随便使用。如果你不得不问这个问题,你可能根本不应该使用NOLOCK。 – 2012-01-09 19:14:19

+1

当你只想做一个脏读时,NOLOCK将忽略作者所持有的锁! – 2012-01-09 19:18:29

+0

如果我知道nolock,我不会问:)这是应用程序在我的工作中的实现方式,我正在调试这个问题。无论在任何查询中他们都使用nolock。我们有近800个存储过程。 – fbhdev 2012-01-09 20:04:46

回答

4

答案是“视情况而定”。

NOLOCK允许“脏读”。这意味着在交易内,您可能会看到来自其他交易的未提交数据。如果您有多个线程更新同一个表中的同一行,您可能会看到其他线程在修改事务之前所修改的数据值。

例如,将表account_balances定义为(account_num int,balance decimal(12,2))。让我们假设会发生以下情况:

//前提下,账户#1有10.00

  1. 线程#平衡1开始交易,递减10
  2. 线程#2开始一个交易账户#1 ,尝试读取帐户#1的余额。它读取的0
  3. 线程#2的平衡减$ 5的帐户,并发出透支给客户(他们的平衡-5)
  4. 线程#1回滚它的事务
  5. 线程#2提交它的交易

//帐户余额现在是-5,即使它应该是5.

什么你不会看到的是一个现场NOLOCK提示中的某种形式的数据不一致的不像在运行多线程代码锁 - 个人写入仍然是原子的。

+1

即使在'read uncommitted'下,编写者也会阻止编写者。因此,线程2将无法更新行,直到线程1的事务完成。除此之外,这是现货。 – zinglon 2012-01-09 19:53:15

+0

已修复,感谢您的支持 – 2012-01-09 19:55:59

+0

因此,如果我期望列中有1,并且它显示为2,那么它可能是线程竞赛而不是与nolock有任何关系? – fbhdev 2012-01-09 20:08:15

2

这意味着您可以获取处于“错误”状态的记录。

例如...

  • 处理1被删除数据
  • 过程2被读取的数据的重叠块的块,使用NOLOCK

在理想情况下,无论是全部由Process1删除的记录可能存在或被删除。因为Process2正在使用NOLOCK,所以它可能会读取某些 Process1正在删除的记录,但不是其他人,因为它们已经消失。

INSERTS和UPDATES也是如此。您可能只是通过以某种方式进行修改来阅读只是其中一部分的记录。


这是否是一个问题,取决于你的数据,你的设计等

搜索引擎不会在乎如果发生这种情况。一家银行负责金融交易。

0

即使使用NOLOCK提示,也不能同时更改相同的记录。

你可以把数据变成不一致的状态。

AFAIK - 无法将此提示应用于目标更新表。

而且 - 这暗示让你阅读未提交的数据,不覆盖他们。

0

小心你如何使用它。潜在的数据不一致。

如果一个查询是 与(NOLOCK)其中可乐= “colAOldvalue”

而另一查询是 组COLC = “colCnewValue” 从表A与(NOLOCK)其中可乐设置可乐= “newColANewvalue” 从表A =“colAOldvalue”

您可以在同一条记录上以colC =“colCnewValue”和colA =“newColANewvalue”结束。如果这不是问题,那么确定。

这是什么驱动?你是否遇到了rowlock或pagelock的性能问题?