我正在使用SSIS 2008在控制流中并行执行多个存储过程。 每个SP应该最终更新表中的1行。
需要注意的是,每个SP都有定义更新特定列的责任。
保证不同的SP不会更新彼此的列。所以要更新的列在不同的SP之间划分,但根据设计,每个SP最终应该在同一行上工作。
目前我的一些SP由于死锁而出错。我猜这可能是因为其他SP锁定该行?
我该如何解决这个问题?
答案 0 :(得分:1)
死锁可能不仅仅是让另一个SP锁定该行。在这种情况下,第一个程序将等到锁定SP释放锁定。这并不是说您的多个程序不会导致问题。不过还有更多。
您可能需要做一些返工以避免问题,但首先您应该了解有关死锁情况的更多信息。我怀疑你对除了正在更新的行以外的对象有锁定。
有很多方法可以收集有关死锁的更多信息。这是一个link,您可以在其中了解死锁详细信息。
答案 1 :(得分:1)
你必须承认,这似乎是一件非常不寻常的事情。我想知道更新单独的表是否更好,然后在最后有一个更新语句将各个表连接到最后一个表? (即update a set a.[1] = ... from a inner join b inner join c
等)。
但是,如果您想继续沿着这条路走下去,那么只需在每个存储过程中设置READ UNCOMMITTED即可。这是最好的选择。
答案 2 :(得分:0)
简单:制作suere你不要把锁留在任何地方。这适用于由连接确定的事务隔离。使用正确的事务isaolation,将没有锁,因此没有死锁。
更新不是问题。它从READS开始。转到READ UNCOMMITED以确保在读取时不保留锁定,和/或使用SELECT语句中的NOLOCK选项单独强制它们保留NO LOCKS以便读取数据(更可取)。 如果然后确保SP在插入(内部或外部)之后几乎立即提交,则应该没有死锁 - 写锁定将导致下一个SP等待第一个事务提交。
特别是当仅限于一个表/一行时,仅使用更新语句IIRC就无法实现死锁。它是读锁,它将延迟锁定(虽然是小延迟)变成死锁。
http://www.eggheadcafe.com/software/aspnet/30976898/how-does-update-lock-prevent-deadlocks.aspx有一个很好的死锁示例。因此,如果所有内容但是更新没有锁定,那么最终就无法实现死锁。
答案 3 :(得分:-1)
行级别锁定尽可能低,所以我认为您必须将更新的表拆分为几个可以彼此独立更新的表。
答案 4 :(得分:-1)
不,两个会话无法同时更新同一行。行级别锁定尽可能低,因此当一个会话更新行时,其他想要更新该记录的会话将等待。
至于死锁,SQL Server的问题在于,如果要求当前正在更新的记录,SELECT语句将默认阻止。如果您不介意阅读未提交的数据,可以使用WITH(NOLOCK)。
所以,如果你有这个事件顺序: SessionA
begin transaction
update t1
set c1 = 'x'
where c2 = 5
SessionB
begin transaction
update t2
set c1 = 'y'
where c2 = 7
SessionA
select * from t1 where c2 = 5
<waits on SessionB>
SessionB
select * from t2 where c2 = 7
<waits on SessionA>...oops. Deadlock.
诀窍是只在必要的时间内锁定一些东西(不要为了释放锁而分解一系列语句 - 确保构成逻辑事务的步骤保留为事务): / p>
begin transaction
update t1
set c1 = 'x'
where c2 = 5
commit
Or(caveat emptor)使用nolock指令:
SessionA
select c1 from t1 where c2 = 5 with (nolock)
<gets the new value of 'x'>
SessionB
select * from t2 where c2 = 7 with (nolock)
<gets the new value of 'y'>