В файле SQL XDL как прочитать атрибут waitresource на узлах процесса, которые находятся в тупике? - PullRequest
2 голосов
/ 17 июня 2010

В SQL Server 2005,

я получаю тупик при обновлении двух разных ключей в одной таблице.

обратите внимание, что эти два ресурса ожидания имеют одинаковую начальную часть, норазные конечные части.

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

и

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

Эти два ключа блокируются, и мне нужно выяснить, почему.

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>

Ответы [ 2 ]

2 голосов
/ 09 августа 2014

Первая часть такая же, потому что она взаимоблокируется с тем же ресурсом (вероятно, индексом), но с другой строкой (2-я часть) ресурса ожидания.С ресурсом ожидания вы можете получить точную строку или страницу, в предыдущем ответе были определены только база данных и таблица или индекс.Замените приведенный ниже код соответствующими идентификаторами в ресурсе ожидания.

В вашем примере 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. Точная строка - получить точную строку или страницу, в вашем конкретном случае ресурсом ожидания был КЛЮЧ, поэтому вы ищете "столбец" %%lockres%% (да, имя столбца на самом деле %% lockres %%, его называют «недокументированной виртуальной колонкой»).Если ваша таблица не слишком устарела или не является операцией DELETE, то вы найдете точную строку из этого хеша, после того как вы определили, из какой таблицы затем «изменен идентификатор раздела» или «hobt_id», измените и запуститеприведенный ниже код (заявление об отказе от ответственности - хеши и расположение страниц могут измениться к тому времени, когда вы выполняете отладку, хотя вряд ли это касается ключевых хешей)

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

Имейте в виду, что обычно2 ресурса конфликтуют, что привело к тупику.Однако это не обязательно должен быть оба оператора , представленных в графе взаимоблокировок, который выполняет обе блокировки.Также возможно, что оператор ранее , но внутри той же транзакции (но не идентифицированный в графе взаимоблокировок) заблокировал 1 из 2 ресурсов.Но 1 из 2 операторов в взаимоблокировке определенно связан с блокировкой 1 из 2 ресурсов, вызывающих взаимоблокировку во время регистрации тупика.

Прежде чем выполнять все вышеперечисленное, если вам пригодитсяИмея графики взаимоблокировок, вы можете отследить это с помощью Profiler или журналов SQL с помощью флага трассировки, но более удобный способ - использовать функцию расширенных событий SQL Server.Просто запустив запрос ниже, вы можете получить графики взаимоблокировок.

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 Server 2008 и 2008 R2: используйте этот запрос.

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
2 голосов
/ 30 октября 2011

6:72057594090487808 - это просто database_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)

...