我正在學習更復雜的SQL Server 2008技術,所以如果我問太明顯的問題,我會提前道歉。t-SQL複合語句導致死鎖,任何想法爲什麼?
我有這樣創建如下表:
CREATE TABLE [dbo].[t_Log_2]
(
[id] INT NOT NULL IDENTITY(1,1) PRIMARY KEY,
[oid] INT,
[idtm] DATETIME2,
[odtm] DATETIME2,
[type] TINYINT,
[state] TINYINT,
[huid] UNIQUEIDENTIFIER,
[cnm] NVARCHAR(256),
[cmdl] NVARCHAR(256),
[batt] TINYINT,
[dvtp0] SMALLINT,
[dvtp1] SMALLINT
);
CREATE INDEX idx_idt
ON [dbo].[t_Log_2]([idtm]);
CREATE INDEX idx_odt
ON [dbo].[t_Log_2]([odtm]);
CREATE INDEX idx_huid
ON [dbo].[t_Log_2]([huid]);
CREATE INDEX idx_cnm
ON [dbo].[t_Log_2]([cnm]);
然後將下面的查詢可以從幾個併發線程從ASP.NET Web應用程序運行。請注意,此整個查詢需要運行原子:
SET XACT_ABORT ON;
BEGIN TRANSACTION;
DELETE FROM [dbo].[t_Log_2]
WHERE [idtm]<'2011-03-12 08:41:57';
WITH ctx AS(
SELECT MIN([idtm]) AS mdIn,
MAX([odtm]) AS mdOut
FROM [dbo].[t_Log_2]
WHERE [type] = 0
AND [state] = 0
AND [huid] = N'18ef4d56-6ef3-906a-a711-88d1bd6ab2d4'
AND [odtm] >= '2013-03-11 06:33:32'
AND [idtm] <= '2013-03-11 06:43:12'
)
INSERT INTO [dbo].[t_Log_2]
([oid],[idtm],[odtm],[type],[state],[huid],
[cnm],[cmdl],[batt],[dvtp0],[dvtp1])
SELECT
2,
CASE WHEN mdIn IS NOT NULL
AND mdIn < '2013-03-11 06:33:32'
THEN mdIn
ELSE '2013-03-11 06:33:32'
END,
CASE WHEN mdOut IS NOT NULL
AND mdOut > '2013-03-11 06:43:12'
THEN mdOut
ELSE '2013-03-11 06:43:12'
END,
0,
0,
N'18ef4d56-6ef3-906a-a711-88d1bd6ab2d4',
null,
null,
0,
1,
null
FROM ctx
SELECT ROWCOUNT_BIG()
DELETE FROM [dbo].[t_Log_2]
WHERE [type] = 0
AND [state] = 0
AND [huid] = N'18ef4d56-6ef3-906a-a711-88d1bd6ab2d4'
AND [odtm] >= '2013-03-11 06:33:32'
AND [idtm] <= '2013-03-11 06:43:12'
AND [id] <> SCOPE_IDENTITY()
DELETE FROM [dbo].[t_Log_2]
WHERE [type] = 0
AND [huid] = N'18ef4d56-6ef3-906a-a711-88d1bd6ab2d4'
AND [idtm] >= (SELECT [idtm] FROM [dbo].[t_Log_2]
WHERE [id] = SCOPE_IDENTITY())
AND [odtm] <= (SELECT [odtm] FROM [dbo].[t_Log_2]
WHERE [id] = SCOPE_IDENTITY())
AND [id] <> SCOPE_IDENTITY()
;WITH ctx1 AS(
SELECT [idtm] AS dI
FROM [dbo].[t_Log_2]
WHERE [id] = SCOPE_IDENTITY()
)
UPDATE [dbo].[t_Log_2]
SET [odtm] = ctx1.dI
FROM ctx1
WHERE [id] <> SCOPE_IDENTITY()
AND [type] = 0
AND [huid] = N'18ef4d56-6ef3-906a-a711-88d1bd6ab2d4'
AND [idtm] < ctx1.dI
AND [odtm] > ctx1.dI
;WITH ctx2 AS(
SELECT [odtm] AS dO
FROM [dbo].[t_Log_2]
WHERE [id] = SCOPE_IDENTITY()
)
UPDATE [dbo].[t_Log_2]
SET [idtm] = ctx2.dO
FROM ctx2
WHERE [id] <> SCOPE_IDENTITY()
AND [type] = 0
AND [huid] = N'18ef4d56-6ef3-906a-a711-88d1bd6ab2d4'
AND [idtm] < ctx2.dO
AND [odtm] > ctx2.dO
COMMIT TRANSACTION;
SET XACT_ABORT OFF
注意,上面的查詢被複制1對1的從動態構成它的C#代碼。實際上,它的參數並非如上所示的硬編碼。
該查詢工作在大部分時間,但一旦我得到的日誌中出現以下錯誤一陣:
事務(進程ID 80)已被死鎖的鎖資源與 另一個進程,並已被選作死鎖受害者。重新運行 交易。
任何想法我該怎麼做才能防止這種僵局?
在您的選擇上使用UPDLOCK提示。 – Arvo 2013-03-12 09:21:41
捕獲並附加死鎖圖形(XML,不是它的圖片!)請參見[保存死鎖圖形(SQL Server Profiler)](http://msdn.microsoft.com/zh-cn/library/ms190465.aspx) – 2013-03-12 09:28:44
@Arvo:你能解釋一下多一點嗎? – c00000fd 2013-03-12 09:29:20