SQL Server 2012:同时在同一个表上运行多个UPDATE FROM SELECT

时间:2014-06-04 10:13:55

标签: sql-server locking sql-update

情况:

1)有大 TABLE1 (9GB数据,20GB idx空间,12M行)
2) TABLE1 上有几个 UPDATE UPDATE / SELECT ,它们逐个运行 3)每个 UPDATE 语句更新不同的列
4)他们都没有使用先前更新的列来计算新的更新列
5)完成所有这些需要一段时间

问题:

我想同时运行那些UPDATE ,但我关注死锁。如何避免它们? SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED 会有帮助吗?

更新看起来像:

update TABLE1 set col1 = subs.col2
from (select ID, col2 from TABLE2) subs
where TABLE1.ID = subs.ID

update TABLE1 set col10 = col2+col3+col4

update TABLE1 set col100 = col2 + subs.col4
from (
    select 
        b.ID, a.col4
    from 
        TABLE3 a 
        join TABLE1 b on TABLE1.ID2 = TABLE3.ID2
) subs
where TABLE1.ID = subs.ID

update TABLE1 set col1000 = col2+col3+col4
from TABLE1
join TABLE4 on TABLE4.date = TABLE1.date
join TABLE5 on TABLE5.ID3 = TABLE1.ID 

3 个答案:

答案 0 :(得分:0)

如果相同的列未更新且未在其他条款中使用,则使用READ UNCOMMITTED进行的脏读操作可能会起作用,但我担心这是一个脆弱的解决方案。

对于更一致的解决方案,您可以混合使用ROWLOCK / UPDLOCK / NOLOCK取决于操作。 F.e。

UPDATE
    TABLE1 WITH (ROWLOCK)
SET
    col1 = TABLE2.col2
FROM
    TABLE1 WITH (ROWLOCK, UPDLOCK)
    INNER JOIN TABLE2 WITH (NOLOCK) ON (TABLE1.ID = TABLE2.ID)

如果您的语句主要更新不同的行,则可以省略ROWLOCK。

在极少数情况下,锁定升级可能会发生,但可能受到

的限制
ALTER TABLE TABLE1 SET (LOCK_ESCALATION = DISABLE)
BTW,您的解决方案的目的是什么?我不认为您会赢得很多性能,而小型部分更新可以比并行的大型更新处理更快。

答案 1 :(得分:0)

(1)更新时避免子查询。多个子查询可能很快导致锁升级并导致死锁。

(2)在TABLOCK vs TABLOCKX查看以下讨论。

(3)对于当前阻止和锁定,请查看How to find out what table a page lock belongs to

处的讨论

答案 2 :(得分:0)

另一种策略:创建一个临时表,其中包含要插入的行的ID以及列的新值。

CREATE TABLE #tmp (
  RowID          int,
  NewCol1Value   ...,
  NewCol2Value   ...,
  NewCol2Value   ...
)

-- Insert into the tmp table
...

UPDATE Table1
  SET  Col1 = ISNULL(NewCol1Value, Col1),
       Col2 = ISNULL(NewCol2Value, Col2),
       ...
  FROM Table1 INNER JOIN #tmp ON Table1.RowID = #tmp.RowID