此SQL(從C#調用)偶爾會導致死鎖。 服務器沒有太多的負載,所以使用的方法是儘可能地鎖定。SqlServer,事務死鎖,什麼時候表被實際鎖定?
-- Lock to prevent race-conditions when multiple instances of an application calls this SQL:
BEGIN TRANSACTION
-- Check that no one has inserted the rows in T1 before me, and that T2 is in a valid state (Test1 != null)
IF NOT EXISTS (SELECT TOP 1 1 FROM T1 WITH(HOLDLOCK, TABLOCKX) WHERE FKId IN {0}) AND
NOT EXISTS(SELECT TOP 1 1 FROM T2 WITH(HOLDLOCK, TABLOCKX) WHERE DbID IN {0} AND Test1 IS NOT NULL)
BEGIN
-- Great! Im the first - go insert the row in T1 and update T2 accordingly. Finally write a log to T3
INSERT INTO T1(FKId, Status)
SELECT DbId, {1} FROM T2 WHERE DbId IN {0};
UPDATE T2 SET LastChangedBy = {2}, LastChangedAt = GETDATE() WHERE DbId IN {0};
INSERT INTO T3 (F1, FKId, F3)
SELECT {2}, DbId, GETDATE() FROM T2 WHERE DbId IN {0} ;
END;
-- Select status on the rows so the program can evaluate what just happened
SELECT FKId, Status FROM T1 WHERE FkId IN {0};
COMMIT TRANSACTION
我相信問題是需要鎖定多個表。
當表格實際上被鎖定時 - 當第一次使用表格時 - 或者在BEGIN TRANS一次鎖定所有表格時,我有點不確定嗎?
+1提到的可序列化模式。更細粒度的行級鎖不易受到死鎖的影響。 – 2009-05-27 19:45:29
是的,表鎖實際上是一個非常糟糕的表現,但如果它是讓事情正常工作的唯一解決方案,那麼它就是一個解決方案。 – 2009-05-28 06:55:29