2

SQL Server 2005では、

同じテーブル内の2つの異なるキーを更新すると、デッドロックが発生します。

以下から、これら2つのwaitresourceの開始部分は同じですが、終了部分が異なることに注意してください。

waitresource="KEY: 6:72057594090487808 (d900ed5a6cc6)" 

waitresource="KEY: 6:72057594090487808 (d900fb5261bb)"

これらの2つのキーはロックされており、その理由を理解する必要があります。

question:_

括弧内の値が異なる場合、キーの前半が同じであるのはなぜですか?

<deadlock-list>
 <deadlock victim="processffffffff8f5863e8">
  <process-list>
   <process id="processaf02f8" taskpriority="0" logused="0" waitresource="KEY: 6:72057594090487808 (d900fb5261bb)" waittime="2281" ownerId="1370264705" transactionname="user_transaction" lasttranstarted="2010-06-17T00:35:25.483" XDES="0x69453a70" lockMode="U" schedulerid="3" kpid="7624" status="suspended" spid="339" sbid="0" ecid="0" priority="0" transcount="2" lastbatchstarted="2010-06-17T00:35:25.483" lastbatchcompleted="2010-06-17T00:35:25.483" clientapp=".Net SqlClient Data Provider" hostname="RISKBBG_VM" hostpid="5848" loginname="RiskOpt" isolationlevel="read committed (2)" xactid="1370264705" currentdb="6" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
    <executionStack>
     <frame procname="MKP_RISKDB.dbo.MarketDataCurrentRtUpload" line="14" stmtstart="840" stmtend="1220" sqlhandle="0x03000600005f9d24c8878f00849d00000100000000000000">
UPDATE c WITH (ROWLOCK) SET LastUpdate = t.LastUpdate, Value = t.Value, Source = t.Source 
        FROM MarketDataCurrent c INNER JOIN #TEMPTABLE2 t ON c.MDID = t.mdid;

        -- Insert new MDID     </frame>
     <frame procname="adhoc" line="1" sqlhandle="0x010006004a58132228bf8d73000000000000000000000000">
MarketDataCurrentBlbgRtUpload     </frame>
    </executionStack>
    <inputbuf>
MarketDataCurrentBlbgRtUpload    </inputbuf>
   </process>
   <process id="processffffffff8f5863e8" taskpriority="0" logused="0" waitresource="KEY: 6:72057594090487808 (d900ed5a6cc6)" waittime="2281" ownerId="1370264646" transactionname="user_transaction" lasttranstarted="2010-06-17T00:35:25.450" XDES="0x1cb72be8" lockMode="U" schedulerid="5" kpid="1880" status="suspended" spid="287" sbid="0" ecid="0" priority="0" transcount="2" lastbatchstarted="2010-06-17T00:35:25.450" lastbatchcompleted="2010-06-17T00:35:25.450" clientapp=".Net SqlClient Data Provider" hostname="RISKAPPS_VM" hostpid="1424" loginname="RiskOpt" isolationlevel="read committed (2)" xactid="1370264646" currentdb="6" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
    <executionStack>
     <frame procname="MKP_RISKDB.dbo.MarketDataCurrent_BulkUpload" line="28" stmtstart="1062" stmtend="1720" sqlhandle="0x03000600a28e5e4ef4fd8e00849d00000100000000000000">
UPDATE c WITH (ROWLOCK) SET LastUpdate = getdate(), Value = t.Value, Source = @source 
FROM MarketDataCurrent c INNER JOIN #MDTUP t ON c.MDID = t.mdid
WHERE c.lastUpdate &lt; @updateTime
and   c.mdid not in (select mdid from MarketData where BloombergTicker is not null and PriceSource like &apos;Live.%&apos;)
and   c.value &lt;&gt; t.value     </frame>
     <frame procname="adhoc" line="1" stmtstart="88" sqlhandle="0x01000600c1653d0598706ca7000000000000000000000000">
exec MarketDataCurrent_BulkUpload @clearBefore, @source     </frame>
     <frame procname="unknown" line="1" sqlhandle="0x000000000000000000000000000000000000000000000000">
unknown     </frame>
    </executionStack>
    <inputbuf>
(@clearBefore datetime,@source nvarchar(10))exec MarketDataCurrent_BulkUpload @clearBefore, @source    </inputbuf>
   </process>
  </process-list>
  <resource-list>
   <keylock hobtid="72057594090487808" dbid="6" objectname="MKP_RISKDB.dbo.MarketDataCurrent" indexname="PK_MarketDataCurrent" id="lock64ac7940" mode="U" associatedObjectId="72057594090487808">
    <owner-list>
     <owner id="processffffffff8f5863e8" mode="U"/>
    </owner-list>
    <waiter-list>
     <waiter id="processaf02f8" mode="U" requestType="wait"/>
    </waiter-list>
   </keylock>
   <keylock hobtid="72057594090487808" dbid="6" objectname="MKP_RISKDB.dbo.MarketDataCurrent" indexname="PK_MarketDataCurrent" id="lockffffffffb8d2dd40" mode="U" associatedObjectId="72057594090487808">
    <owner-list>
     <owner id="processaf02f8" mode="U"/>
    </owner-list>
    <waiter-list>
     <waiter id="processffffffff8f5863e8" mode="U" requestType="wait"/>
    </waiter-list>
   </keylock>
  </resource-list>
 </deadlock>
</deadlock-list>
4

2 に答える 2

2

これ6:72057594090487808database_id:hobtid、XDLのさらに下に見られるとおりです。

<keylock hobtid="72057594090487808" dbid="6"  
objectname="MKP_RISKDB.dbo.MarketDataCurrent" 
indexname="PK_MarketDataCurrent" id="lock64ac7940" mode="U" 
associatedObjectId="72057594090487808">

括弧内の数字は、内のさまざまなキーのハッシュ値です。MKP_RISKDB.dbo.MarketDataCurrent(PK_MarketDataCurrent)

于 2011-10-30T11:51:29.303 に答える
2

最初の部分は同じです。同じリソース(インデックスの可能性が高い)でデッドロックが発生しますが、待機リソースの行(2番目の部分)が異なります。待機リソースを使用すると、実際に正確な行またはページを取得できます。前の回答では、データベースとテーブルまたはインデックスのみが識別されていました。以下のコードを、waitresource内の適切なIDに置き換えます。

あなたの例ではwaitresource="KEY: 6:72057594090487808 (d900ed5a6cc6)

  1. データベース-デッドロックに関係するデータベースを取得します

    SELECT * FROM sys.databases WHERE database_id IN (6)
    
  2. テーブルまたはインデックス-デッドロックに関係するテーブルまたはインデックスを取得します

    SELECT b.name AS TableName, 
           c.name AS IndexName, c.type_desc AS IndexType, * 
    FROM sys.partitions a
    INNER JOIN sys.objects b 
       ON a.object_id = b.object_id
    INNER JOIN sys.indexes c 
       ON a.object_id = c.object_id  AND a.index_id = c.index_id
    WHERE partition_id IN ('72057594090487808')
    
  3. 正確な行-正確な行またはページを取得します。特定のケースでは待機リソースがKEYであったため、「列」を検索します%%lockres%%(はい、列名は実際には%% lockres %%であり、「ドキュメント化されていない仮想列」と呼ばれます) )。テーブルが古すぎない場合、またはDELETE操作でない場合は、「パーティションID」または「hobt_id」がどのテーブルからのものであるかを判別した後、そのハッシュから正確な行を見つけて変更し、実行します。以下のコード(免責事項-ハッシュとページの場所は、デバッグを実行するまでに変更されている可能性がありますが、キーハッシュではありそうにありません)

    SELECT 
       sys.fn_PhysLocFormatter(%%physloc%%) AS PageResource, 
       %%lockres%% AS LockResource, *
    FROM <<InsertTableNameFromStep2Here>>
    WHERE %%lockres%% IN ('(d900ed5a6cc6)')
    

通常、2つのリソースが競合しているため、デッドロックが発生していることに注意してください。ただし、両方のロックを実行しているのは、必ずしもデッドロックグラフで提供されている両方のステートメントである必要はありません。また、のステートメントが同じトランザクション内で(ただし、デッドロックグラフで識別されていない)、2つのリソースのうちの1つをロックした可能性もあります。ただし、デッドロック内の2つのステートメントのうちの1つは、デッドロックがログに記録されたときにデッドロックを引き起こした2つのリソースのうちの1つをロックすることに確実に関係しています。

上記のすべてを実行する前に、デッドロックグラフがある場合に便利な場合は、プロファイラーまたはトレースフラグ付きのSQLログを使用してこれをトレースできますが、より便利な方法は、SQLServer拡張イベント機能を使用することです。以下のクエリを実行するだけで、デッドロックグラフを取得できます。

SELECT
   DATEADD(mi, DATEDIFF(mi, GETUTCDATE(), CURRENT_TIMESTAMP), DeadlockEventXML.value('(event/@timestamp)[1]', 'datetime2')) AS [EventTime],
   DeadlockEventXML.value('(//process[@id[//victim-list/victimProcess[1]/@id]]/@hostname)[1]', 'nvarchar(max)') AS HostName,
   DeadlockEventXML.value('(//process[@id[//victim-list/victimProcess[1]/@id]]/@clientapp)[1]', 'nvarchar(max)') AS ClientApp,
   DB_NAME(DeadlockEventXML.value('(//process[@id[//victim-list/victimProcess[1]/@id]]/@currentdb)[1]', 'nvarchar(max)')) AS [DatabaseName],
   DeadlockEventXML.value('(//process[@id[//victim-list/victimProcess[1]/@id]]/@transactionname)[1]', 'nvarchar(max)') AS VictimTransactionName,
   DeadlockEventXML.value('(//process[@id[//victim-list/victimProcess[1]/@id]]/@isolationlevel)[1]', 'nvarchar(max)') AS IsolationLevel,
   DeadlockEventXML.query('(event/data[@name="xml_report"]/value/deadlock)[1]') AS DeadLockGraph,
   DeadlockEventXML
FROM
(
   SELECT 
      XEvent.query('.') AS DeadlockEventXML,
     Data.TargetData
   FROM 
   (
      SELECT 
        CAST(target_data AS XML) AS TargetData
        FROM sys.dm_xe_session_targets st
        JOIN sys.dm_xe_sessions s ON s.address = st.event_session_address
        WHERE s.name = 'system_health' AND
          st.target_name = 'ring_buffer'
   ) AS Data
   CROSS APPLY TargetData.nodes('RingBufferTarget/event[@name="xml_deadlock_report"]') AS XEventData(XEvent)
) AS DeadlockInfo

SQL Server2008および2008R2の場合は、このクエリを使用します。

SELECT
   DATEADD(mi, DATEDIFF(mi, GETUTCDATE(), CURRENT_TIMESTAMP), DeadlockEventXML.value('(event/@timestamp)[1]', 'datetime2')) AS [EventTime],
   DeadlockEventXML.value('(//process[@id[//victim-list/victimProcess[1]/@id]]/@hostname)[1]', 'nvarchar(max)') AS HostName,
   DeadlockEventXML.value('(//process[@id[//victim-list/victimProcess[1]/@id]]/@clientapp)[1]', 'nvarchar(max)') AS ClientApp,
   DB_NAME(DeadlockEventXML.value('(//process[@id[//victim-list/victimProcess[1]/@id]]/@currentdb)[1]', 'nvarchar(max)')) AS [DatabaseName],
   DeadlockEventXML.value('(//process[@id[//victim-list/victimProcess[1]/@id]]/@transactionname)[1]', 'nvarchar(max)') AS VictimTransactionName,
   DeadlockEventXML.value('(//process[@id[//victim-list/victimProcess[1]/@id]]/@isolationlevel)[1]', 'nvarchar(max)') AS IsolationLevel,
   DeadlockEventXML.query('(event/data[@name="xml_report"]/value/deadlock)[1]') AS DeadLockGraph,
   DeadlockEventXML
FROM
(
   SELECT 
            CONVERT(XML,REPLACE(REPLACE(CONVERT(VARCHAR(MAX),XEvent.query('.')), '&lt;', '<'), '&gt;', '>'))
   AS DeadlockEventXML,
     Data.TargetData
   FROM 
   (
      SELECT 
        CAST(target_data AS XML) AS TargetData
        FROM sys.dm_xe_session_targets st
        JOIN sys.dm_xe_sessions s ON s.address = st.event_session_address
        WHERE s.name = 'system_health' AND
          st.target_name = 'ring_buffer'
   ) AS Data
   CROSS APPLY TargetData.nodes('RingBufferTarget/event[@name="xml_deadlock_report"]') AS XEventData(XEvent)
) AS DeadlockInfo
于 2014-08-08T20:47:40.640 に答える