情况:
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
答案 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