5

SQL Server 2005 で実行する 2 つのストアド プロシージャを別々のスレッドで実行しています。1 つのプロシージャは一連のテーブルに新しい行を挿入し、もう 1 つのプロシージャは同じテーブル セットから古いデータを削除します。これらのプロシージャは、テーブルDLevelおよびModelでデッドロックに陥っています。スキーマは次のとおりです。

スクロールバー画像
(出典: barramsoft.com )

Table DFile : Primary Key = DFileID
Table DLevel : Primary Key = DLevelID, Foreign Key: DFileID
Table Model : Primary Key = ModelID, Foreign Key: DFileID
Table ELement : Primary key = ElementID, Foreign Key1: DFileID, Foreign Key2: DLevelID

デッドロックの原因となっている正確に 2 つの SQL ステートメント (各ストアド プロシージャから 1 つ) を分離しました。いずれかの手順でデッドロックが報告されるのを見てきました。どちらの場合も top (1000) を使用し、削除/挿入する行がなくなるまで、両方のステートメントがループで実行されます。

SQL ステートメント 1:

while (...)
begin
    delete top (1000) from DLevel where DFileID = @fileID1
    ...
end

SQL ステートメント 2:

while (...)
begin
    insert into Element (ElementID, DFileID, LevelNum, ...)
       select top (1000) el.ElementID, el.DFileID, el.LevelNum, ...
       from   ElementLoader el with (nolock)
              left outer join Element e with (nolock)
                   on e.ElementID = el.ElementID
       where  el.DFileID = @fileID2
       and    e.ElementID is null
       order  by el.ElementID
    ...
end

注: @fileID1@fileID2の値は、常に異なることが保証されています。DLevel テーブルの平均値は約 1 です。1 つのDFileIDに対して 60 行であるため、1回のパスですべての行の削除が完了します。

これら 2 つの SQL ステートメント間のデッドロックを回避するにはどうすればよいですか?

編集 1: 問題をより明確にするために書き直しました。追加画像; SQL を簡素化し、DLevel テーブルへの結合を削除しましたが、デッドロックの原因にはなりませんでした。

編集 2: デッドロック グラフの XML を追加しました。Modelテーブル
でデッドロックが発生するようになりました。DLevelテーブルと同様のモデルの削除ステートメントとスキーマ。

<deadlock victim="process2bae38">
    <process-list>
        <process id="process2bae38" taskpriority="0" logused="4760" waitresource="PAGE: 11:1:1946" waittime="46" ownerId="4127445" transactionname="DELETE" lasttranstarted="2010-06-24T16:19:00.107" XDES="0xffffffff90552ae0" lockMode="S" schedulerid="1" kpid="14252" status="suspended" spid="58" sbid="0" ecid="0" priority="0" transcount="2" lastbatchstarted="2010-06-24T16:19:00.107" lastbatchcompleted="2010-06-24T16:19:00.107" clientapp=".Net SqlClient Data Provider" hostname="LT0103" hostpid="1668" loginname="NT AUTHORITY\SYSTEM" isolationlevel="read committed (2)" xactid="4127445" currentdb="11" lockTimeout="4294967295" clientoption1="673185824" clientoption2="128056">
            <executionStack>
                <frame procname="CadExplorer5.dbo.pCleanUpOldFiles" line="364" stmtstart="23718" stmtend="23834" sqlhandle="0x03000b00fb1c2229b1a7f7009f9d00000100000000000000">
delete top (@batchSize) from Model where DFileID = @fileID     </frame>
            </executionStack>
            <inputbuf>
Proc [Database Id = 11 Object Id = 690101499]    </inputbuf>
        </process>
        <process id="process2c95b8" taskpriority="0" logused="283388" waitresource="KEY: 11:72057594039304192 (8100bdf15e8b)" waittime="78" ownerId="4127412" transactionname="INSERT" lasttranstarted="2010-06-24T16:19:00.103" XDES="0xffffffff81d5ef18" lockMode="S" schedulerid="2" kpid="8460" status="suspended" spid="63" sbid="0" ecid="0" priority="0" transcount="2" lastbatchstarted="2010-06-24T16:18:59.413" lastbatchcompleted="2010-06-24T16:18:59.413" clientapp=".Net SqlClient Data Provider" hostname="LT0103" hostpid="1668" loginname="NT AUTHORITY\SYSTEM" isolationlevel="read committed (2)" xactid="4127412" currentdb="11" lockTimeout="4294967295" clientoption1="673185824" clientoption2="128056">
            <executionStack>
                <frame procname="CadExplorer5.dbo.pLoadElements" line="288" stmtstart="28796" stmtend="33194" sqlhandle="0x03000b00a689fe2b2c5107019f9d00000100000000000000">
insert into Element (
                        ElementID, DFileID, ModelID, ElementTypeID, CADElementID,
                        ParentID,
                        LevelNum,
                        Depth, NumChildren,
                        Color, Weight, Style, Xlo, Ylo, Zlo, Xhi, Yhi, Zhi,
                        Diagonal, XCenter,
                        BitFlags, ElementModTime
                        )
                  select top (@batchSize)
                        el.ElementID, el.DFileID, el.ModelID, el.ElementTypeID, el.CADElementID,
                        parent.ElementID as ParentID,
                        (case when el.LoaderType = 1 and et.IsGraphical = 1 then el.LevelAttrib else null end) as LevelNum,
                        --l.LevelNum,
                        el.Depth, el.NumChildren,
                        el.Color, el.Weight, el.Style, el.Xlo, el.Ylo, el.Zlo, el.Xhi, el.Yhi, el.Zhi,
                        el.Diagonal, el.XCenter,     </frame>
            </executionStack>
            <inputbuf>
Proc [Database Id = 11 Object Id = 738101670]    </inputbuf>
        </process>
    </process-list>
    <resource-list>
        <pagelock fileid="1" pageid="1946" dbid="11" objectname="CadExplorer5.dbo.Element" id="lockffffffff86ffd080" mode="IX" associatedObjectId="72057594039107584">
            <owner-list>
                <owner id="process2c95b8" mode="IX"/>
            </owner-list>
            <waiter-list>
                <waiter id="process2bae38" mode="S" requestType="wait"/>
            </waiter-list>
        </pagelock>
        <keylock hobtid="72057594039304192" dbid="11" objectname="CadExplorer5.dbo.Model" indexname="PK_Model" id="lockffffffff8d66db80" mode="X" associatedObjectId="72057594039304192">
            <owner-list>
                <owner id="process2bae38" mode="X"/>
            </owner-list>
            <waiter-list>
                <waiter id="process2c95b8" mode="S" requestType="wait"/>
            </waiter-list>
        </keylock>
    </resource-list>
</deadlock>
4

3 に答える 3

1

Element テーブルから DLevel.DFileID への外部キーを削除してみてください。DLevel.DlevelID に主キーがあり、それを Element の外部キーとして参照するため、DFileID 外部キーは実際には必要ありません。

于 2010-06-25T14:57:22.770 に答える
1

1 つの考えられるシナリオ: 1 つの接続が Element に行を挿入し、その行が DLevel の行を参照し、DLevel のその行が別の接続によって削除されています。nolock ヒントは外部キーには適用されません。

于 2010-06-24T18:51:33.620 に答える
0

削除と挿入が同時に行われる何らかのキー違反があるに違いないと思います..?

于 2010-06-24T18:28:58.130 に答える