2012-05-02 12 views
2

まず、デッドロックを100%防げる必要はありませんが、減らすためにできることは何かいいです。このSQLで発生するデッドロックを防ぐ方法

私は2つのテーブルSourceDestを持っています。ソースにユニークな値のロードがあり、Sourceから新しい値をリクエストする必要があります。その際、Destに移動してください。

私は、次のSQLを持っている:複数のユーザーが同じvalue行を取得するとき

begin tran 
    declare @value 
    select top 1 @value = [value] from [source] 
    delete from [Source] where [value][email protected] 
    insert into [Dest] ([Value]) values (@value) 
    select @value 
commit tran 

これは時折デッドロックをスローします。これを防ぐ/減らすにはどうすればいいですか?

イムは、私はへの書き込み/から読んでいますSourceDest内の他の列がある、余談としてSQL Server 2008の

を使用します。これは、簡潔さのために簡素化されています。

おかげ

+1

XLOCKをつかむことができ - あなたの根本的な問題が一つではありませんあなたは尋ねています...あなたはどんな孤立レベルですか? –

+0

デフォルトですので、 'READ COMMITTED'と仮定します。 –

答えて

3

それはソースから値を削除し、単一のアトミック操作でそれを返しますので、あなたは、OUTPUT句をあなたのDELETEコマンドを使用して、この競合状態を避けることができます。私はコンセプトを実証するために、次のスクリプトを作っ:

-- dummy data 
CREATE TABLE #source (mycolumn INT); 
CREATE TABLE #destination (mycolumn INT); 

INSERT #source VALUES (1); 
INSERT #source VALUES (2); 
INSERT #source VALUES (3); 
GO 

-- stored procedure to demonstrate concept 
CREATE PROCEDURE move 
AS BEGIN 
    BEGIN TRANSACTION; 

    DECLARE @tmp TABLE (mycolumn INT); 
    DELETE TOP(1) #source OUTPUT DELETED.mycolumn INTO @tmp(mycolumn); 

    INSERT #destination (mycolumn) OUTPUT INSERTED.mycolumn 
    SELECT mycolumn 
    FROM @tmp; 

    COMMIT; 
END 
GO 

-- testing 
EXEC move; 
GO -- remove from 1 from #source, insert 1 into #destination, returns 1 

EXEC move; 
GO -- remove from 2 from #source, insert 2 into #destination, returns 2 

EXEC move; 
GO -- remove from 3 from #source, insert 3 into #destination, returns 3 
+0

私はちょうど' OUTPUT'を発見しました。私は自分の実現可能性について質問するために質問を更新しようとしていました。 +1 –

+0

おそらく 'OUTPUT DELETE'はアトミック/' WAIT'を引き起こすだけの行ロックを引き起こしますか? –

+1

実際には、この節では同じ値を#sourceテーブルから複数回返すことはできないため、元の競合状態は回避されます。私はSQL Server内部でどのようにそのメカニズムを実装しているのかよく分かりませんが、このコンテキストでは重要ではありません。 –

1

「複数のユーザーが同じ値の行を取得するときに、」あなたはSELECT声明

begin tran 
    declare @value 
    select top 1 @value = [value] from [source] with (XLOCK) 
    delete from [Source] where [value][email protected] 
    insert into [Dest] ([Value]) values (@value) 
    select @value 
commit tran 
関連する問題