2

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 テーブルを確認しましたが、新しいデッドロック イベントは含まれていません。以前に他のデッドロックを見たことがありますが、それらはすべて私が処理できる例外をスローしました。これは無期限にハングします。

ちなみに、2 番目の操作を 50 ミリ秒遅らせると、正常に動作します。

4

1 に答える 1

0

ここでの停止は、実際にはデッドロックが原因ではなく、既に経過した時間を待っているためです。以下は、私の実行からのメッセージとともに現在の時刻をスパムするクエリの修正版です。ご覧のとおり、@MyDateTime2 を待っているときには、すでに過ぎています。50 ミリ秒が機能する理由は、すべての作業を行うのに 50 ミリ秒もかからないからです。WAITFOR TIME を WAITFOR DELAY に変更したところ、うまくいきました。ただし、実際には 1 ミリ秒も待ちません。

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 を使用します。 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
于 2013-06-21T20:17:09.047 に答える