2013-03-25 44 views
2

我在我的SQL Azure数据库上遇到一些由并发删除操作导致的死锁,我不确定如何解决它。我已将情况简化到最基本的水平。我有以下表格:SQL Azure:并发删除操作造成的死锁

CREATE TABLE [dbo].[Test2013](
    [ClientID] [int] NOT NULL, 
    [ID] [uniqueidentifier] NOT NULL, 
    [Value] [int] NOT NULL, 
CONSTRAINT [dbo-Test2013] PRIMARY KEY CLUSTERED 
(
    [ClientID] ASC, 
    [ID] ASC 
) 
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, 
     IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, 
     ALLOW_PAGE_LOCKS = ON) 
) 

GO 

ALTER TABLE [dbo].[Test2013] ADD CONSTRAINT [Test2013-ID-Default-Value] 
    DEFAULT (newid()) FOR [ID] 
GO 

导致问题如下所示的查询:

INSERT INTO [Test2013] 
    ([ClientID],[ID],[Value]) 
    SELECT 
     CAST(-2147483648 AS INT) [ClientID], 
     '82ecb924-d2f0-44ee-9a8e-5240d12de088' [ID], 
     CAST(1 AS INT) [Value] 

INSERT INTO [Test2013] 
    ([ClientID],[ID],[Value]) 
    SELECT 
     CAST(-2147483648 AS INT) [ClientID], 
     '82ecb924-d2f0-44ee-9a8e-5240d12de077' [ID], 
     CAST(2 AS INT) [Value] 

DECLARE @MyDateTime DATETIME 
SET @MyDateTime = DATEADD(s,5,GETDATE()) 

DECLARE @MyDateTime2 DATETIME 
SET @MyDateTime2 = DATEADD(ms,1,@MyDateTime) 

BEGIN tran 
    WAITFOR TIME @MyDateTime; 
    DELETE FROM [Test2013] 
    WHERE [ID] = '82ecb924-d2f0-44ee-9a8e-5240d12de088'; 
Commit tran 

BEGIN tran 
    WAITFOR TIME @MyDateTime2; 
    DELETE FROM [Test2013] 
    WHERE [ID] = '82ecb924-d2f0-44ee-9a8e-5240d12de077'; 
Commit tran 

我想这将是比较琐碎,但我无法找出什么是真正锁定的查询。我检查了sys.events_log表,它不包含任何新的死锁事件。我之前看到过其他的僵局,但他们都抛出了我可以处理的异常,这个只是无限期地悬挂下来。

在一个侧面说明,如果我延迟第二次操作50毫秒,它工作正常。

+1

只是一个评论,但你尝试每个插入后“去”? – Paparazzi 2013-03-25 20:21:33

+1

呃... Derp。那是愚蠢的。是的,它现在起作用。仍然不能在我的更复杂的版本,但这是我的问题(可能是一个触发器,我没有想到的地方锁)。 – 2013-03-25 21:45:45

+0

@Blam:“GO”到底有什么帮助? – sharptooth 2013-03-26 07:07:40

回答

0

挂在这里并不是真的造成死锁,而是因为你在等待已经过去的时间。下面是您的查询的修改版本,它会将当前时间与我运行的消息一起进行传播。正如你所看到的,当你等待@ MyDateTime2时,它已经通过了。 50 ms工作的原因是因为它不需要50 ms来完成所有这些工作。我将WAITFOR TIME改为WAITFOR DELAY,并且工作正常。不过,它并不等待一毫秒。

INSERT INTO [Test2013] 
    ([ClientID],[ID],[Value]) 
    SELECT 
     CAST(-2147483648 AS INT) [ClientID], 
     '82ecb924-d2f0-44ee-9a8e-5240d12de088' [ID], 
     CAST(1 AS INT) [Value] 

INSERT INTO [Test2013] 
    ([ClientID],[ID],[Value]) 
    SELECT 
     CAST(-2147483648 AS INT) [ClientID], 
     '82ecb924-d2f0-44ee-9a8e-5240d12de077' [ID], 
     CAST(2 AS INT) [Value] 

DECLARE @MyDateTime DATETIME 
SET @MyDateTime = DATEADD(s,5,GETDATE()) 

PRINT(CONVERT(varchar, @MyDateTime, 121)) 
DECLARE @MyDateTime2 DATETIME 
SET @MyDateTime2 = DATEADD(ms,1,@MyDateTime) 

PRINT(CONVERT(varchar, @MyDateTime2, 121)) 
BEGIN tran 
PRINT(CONVERT(varchar, getdate(), 121)) 
    WAITFOR TIME @MyDateTime; 
PRINT(CONVERT(varchar, getdate(), 121)) 
    DELETE FROM [Test2013] 
    WHERE [ID] = '82ecb924-d2f0-44ee-9a8e-5240d12de088'; 
PRINT(CONVERT(varchar, getdate(), 121)) 
Commit tran 

BEGIN tran 
PRINT(CONVERT(varchar, getdate(), 121)) 
    WAITFOR TIME @MyDateTime2; 
PRINT(CONVERT(varchar, getdate(), 121)) 
    DELETE FROM [Test2013] 
    WHERE [ID] = '82ecb924-d2f0-44ee-9a8e-5240d12de077'; 
PRINT(CONVERT(varchar, getdate(), 121)) 
Commit tran 

而产生的消息时,我取消查询:

(1 row(s) affected) 

(1 row(s) affected) 
2013-06-21 15:13:09.980 
2013-06-21 15:13:09.980 
2013-06-21 15:13:04.980 
2013-06-21 15:13:09.997 

(1 row(s) affected) 
2013-06-21 15:13:09.997 
2013-06-21 15:13:10.017 
Query was cancelled by user. 

使用WAITFOR DELAY代替:INSERT INTO [Test2013] ([客户端ID],[ID],[值]) SELECT CAST (-2147483648 AS INT)[客户端ID], '82ecb924-d2f0-44ee-9a8e-5240d12de088'[ID], CAST(1 AS INT)[数值]

INSERT INTO [Test2013] 
    ([ClientID],[ID],[Value]) 
    SELECT 
     CAST(-2147483648 AS INT) [ClientID], 
     '82ecb924-d2f0-44ee-9a8e-5240d12de077' [ID], 
     CAST(2 AS INT) [Value] 


BEGIN tran 
PRINT(CONVERT(varchar, getdate(), 121)) 
    WAITFOR delay '00:00:05' 
PRINT(CONVERT(varchar, getdate(), 121)) 
    DELETE FROM [Test2013] 
    WHERE [ID] = '82ecb924-d2f0-44ee-9a8e-5240d12de088'; 
PRINT(CONVERT(varchar, getdate(), 121)) 
Commit tran 

BEGIN tran 
PRINT(CONVERT(varchar, getdate(), 121)) 
    WAITFOR delay '00:00:00.001' 
PRINT(CONVERT(varchar, getdate(), 121)) 
    DELETE FROM [Test2013] 
    WHERE [ID] = '82ecb924-d2f0-44ee-9a8e-5240d12de077'; 
PRINT(CONVERT(varchar, getdate(), 121)) 
Commit tran