이 SQL (C#에서 호출 됨)은 때때로 교착 상태가됩니다. 서버에 부하가 많이 걸리지 않으므로 가능한 한 많이 잠그는 것이 사용됩니다.SqlServer, Transaction deadlock, 테이블이 실제로 잠겨있는 경우?
-- 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
저는 여러 테이블을 잠글 필요가 있다고 생각합니다.
테이블이 실제로 xlocked 될 때 - 처음 테이블을 사용할 때 - 또는 BEGIN TRANS에서 한 번에 모든 테이블을 잠글 때 약간 확신 할 수 없습니까?
+1은 직렬화 가능 모드를 언급합니다. 더 세분화 된 행 레벨 잠금은 데드락에 덜 민감합니다. –
예, 테이블 잠금은 실제로는 성능이 현저히 나쁜 것은 사실이지만, 제대로 작동하게하는 유일한 솔루션이라면 솔루션입니다. –