2

まず、デッドロックを100%防ぐ必要はありませんが、デッドロックを減らすためにできることは何でもいいでしょう。

私は2つのテーブルSourceとを持っていDestます。ソースには一意の値がたくさんあります。新しい値を要求する必要があります。Sourceその際、に移動しDestます。

私は次のSQLを持っています:

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

valueこれにより、複数のユーザーが同じ行を取得したときにデッドロックが発生することがあります。どうすればこれを防ぐ/減らすことができますか?

SQLServer2008を使用しています

余談ですが、他の列がSourceありDest、私はこの列から読み取り/書き込みを行っています。これは簡潔にするための簡略化です。

ありがとう

4

2 に答える 2

3

DELETEコマンドでOUTPUT句を使用すると、ソースから値が削除され、単一のアトミック操作で返されるため、この競合状態を回避できます。概念を示すために、次のスクリプトを作成しました。

-- 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
于 2012-05-02T16:42:26.857 に答える
1

XLOCKあなたはSELECT声明でつかむことができます

begin tran
    declare @value
    select top 1 @value = [value] from [source] with (XLOCK)
    delete from [Source] where [value]=@value
    insert into [Dest] ([Value]) values (@value)
    select @value
commit tran
于 2012-05-02T17:38:57.847 に答える