死锁 - 这真的有用吗?

时间:2010-07-30 17:56:57

标签: sql sql-server deadlock

所以我有一个问题让我陷入困境。熟悉系统的人无法弄清楚为什么sproc会死锁,但他们告诉我我应该把它添加到它:

SET NOCOUNT ON
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

这真的是一个有效的解决方案吗?那是做什么的?

5 个答案:

答案 0 :(得分:6)

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

这将导致系统返回不一致的数据,包括重复记录和丢失记录。请阅读Previously committed rows might be missed if NOLOCK hint is usedTimebomb - The Consistency problem with NOLOCK / READ UNCOMMITTED

如果您遵循正确的程序,可以调查和修复死锁,这不是什么大问题。当然,扔一个肮脏的阅读可能看起来更容易,但在路上,你会长时间盯着你的总账,并想知道为什么这样做平衡借记和信用。所以请再读一遍,直到你真的理解这一点:脏读不一致

如果您想获得监狱卡,请启用snapshot isolation

ALTER DATABASE MyDatabase
SET READ_COMMITTED_SNAPSHOT ON

但请记住,快照隔离修复死锁,它只隐藏它们。正确调查死锁原因和修复始终是适当的操作。

答案 1 :(得分:5)

NOCOUNT将使您的查询不会将返回的行数返回给调用应用程序(即受影响的1000000行)。

交易隔离级别读取不满意将允许显示脏读“here.

隔离级别可能会有所帮助,但是您是否希望允许脏读?

答案 2 :(得分:3)

向查询中随机添加SET选项不太可能帮助我害怕

SET NOCOUNT ON

对此问题没有任何影响。

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

将阻止您的查询取出共享锁。除了读取“脏”数据之外,它还可以导致您的查询读取相同的行两次,或者根本不读取,这取决于正在发生的其他并发活动。

这是否能解决死锁问题取决于死锁的类型。如果由于锁定请求的非线性排序导致2个写入器死锁,则它将完全没有效果。 (事务1更新行a,事务2更新行b然后tran 1请求锁定b和tran 2请求锁定a)

你能发布有问题的查询和死锁图吗? (如果您使用的是SQL 2005或更高版本)

答案 3 :(得分:2)

最佳指南是:

http://technet.microsoft.com/es-es/library/ms173763.aspx

段:

  

指定语句可以读取已被其他人修改的行   交易但尚未提交。

     

在READ上运行的事务   未达到的水平不会分享   锁定以防止其他事务   从修改数据读取   当前交易。阅读不满意   交易也不会被阻止   独家锁定会阻止   读取行的当前事务   已被修改但没有   由其他交易承诺。什么时候   此选项已设置,可以   读取未提交的修改,其中   被称为脏读。价值观   数据可以更改,行可以   在数据集中出现或消失   在交易结束之前。   此选项具有相同的效果   在所有表中设置NOLOCK   事务中的SELECT语句。   这是最不受限制的   隔离级别。

     

在SQL Server中,您也可以最小化   保护时锁定争用   来自脏读的交易   使用未提交的数据修改   之一:

     

READ COMMITTED隔离级别   使用READ_COMMITTED_SNAPSHOT   数据库选项设置为ON。该   SNAPSHOT隔离级别

答案 4 :(得分:0)

另一方面,还有两个方面需要考虑,这可能有所帮助。

1)索引和SQL使用的索引。表上使用的索引策略将影响受影响的行数。如果使用唯一索引进行数据修改,则可以减少死锁的可能性。

一种算法 - 当然它不适用于所有情况。使用NOLOCK是有针对性的,而不是全球性的。

The "old" way:
UPDATE dbo.change_table
   SET somecol = newval
 WHERE non_unique_value = 'something'

The "new" way:
INSERT INTO #temp_table
    SELECT uid FROM dbo.change_table WITH (NOLOCK)
     WHERE non_unique_value = 'something'

UPDATE dbo.change_table
   SET somecol = newval
  FROM dbo.change_table c
       INNER JOIN
       #temp_table t
       ON (c.uid = t.uid)

2)交易持续时间 交易开放的时间越长,可能存在争用的可能性越大。如果有办法减少记录保持锁定的时间,则可以减少发生死锁的可能性。 例如,在代码的开头执行尽可能多的SELECT语句(例如查找),而不是执行INSERT或UPDATE,然后执行查找,然后执行INSERT,然后执行另一次查找。 这是可以在“静态”表上使用NOLOCK提示选择SELECT,而不会改变代码的锁定“足迹”。