2010-06-17 16 views
2

Sur SQL Server 2005,Dans un fichier SQL XDL, comment lire l'attribut waitresource sur les noeuds de processus qui se bloquent?

Je rencontre un blocage en mettant à jour deux clés différentes dans la même table.

notons ci-dessous que ces deux ressources wait ont la même partie initiale, mais des parties terminales différentes.

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

et

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

Ces deux touches sont de verrouillage, et je dois comprendre pourquoi.

Le question:

Si les valeurs entre parenthèses sont différentes, pourquoi sont la première moitié de la clé de la même chose?

<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> 
+0

Selon: http://consultingblogs.emc.com/jamesrowlandjones/archive/2009/05/28/the-curious-case-of-the-dubious-deadlock-and-the-not- so-logical-lock.aspx # comments La valeur entre parenthèses est la ressource de verrouillage et on peut utiliser le mot clé '%% lockres %%' sur une ligne pour déterminer cette valeur pour n'importe quelle ligne. Mais ce que j'ai est un blocage sur deux valeurs distinctes '%% lockres %%'. Quelle est la première moitié de cette clé et pourquoi est-ce la même chose? Est-ce la collision de hash dont il parle? – skimania

+0

Sainte fumée! Personne n'a de réponse à ça? Quelqu'un veut même prendre une photo? – skimania

+0

Je n'ai même pas de Tumbleweed pour ça? – skimania

Répondre

2

Le 6:72057594090487808 est juste le database_id:hobtid comme on le verra plus loin dans la XDL.

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

Les chiffres entre parenthèses sont les valeurs hachurées pour différentes touches dans MKP_RISKDB.dbo.MarketDataCurrent(PK_MarketDataCurrent)

+0

Oui, c'est correct. Désolé, je n'ai pas vu ça plus tôt. Merci. – skimania

2

La première partie est la même parce que son supercondamnation sur la même ressource (indice probable), mais différent rang (2e partie) de attendre la ressource. Avec la ressource d'attente vous pouvez réellement obtenir la ligne ou la page exacte, la réponse précédente avait seulement la base de données et la table ou l'index identifié. Remplacez le code ci-dessous par les ID appropriés dans la source wait.

Dans votre exemple waitresource="KEY: 6:72057594090487808 (d900ed5a6cc6)

  1. Database - récupérer la base de données impliquée dans l'impasse avec

    SELECT * FROM sys.databases WHERE database_id IN (6) 
    
  2. table ou un index - récupérer la table ou l'index impliqué dans l'impasse

    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. Row exacte - récupérer la ligne exacte ou d'une page, dans votre cas la ressource d'attente était une clé, si vous recherchez la « colonne » %%lockres%% (oui, le nom de la colonne est en réalité %% lockres %%, son connue comme une "colonne virtuelle non documentée"). Si votre table n'est pas trop obsolète ou s'il ne s'agit pas d'une opération DELETE, vous trouverez la ligne exacte de ce hachage, après avoir déterminé la table à partir de laquelle "partition id" ou "hobt_id" est puis modifiez et exécutez le code ci-dessous (disclaimer - les hash et les emplacements de page peut avoir changé au moment où vous faites la mise au point, bien qu'improbable avec les hash clés)

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

Gardez à l'esprit que généralement 2 ressources sont contradictoires qui causé l'impasse.Cependant, il ne doit pas nécessairement être les deux instructions fournies dans le graphique de blocage qui effectue les deux le verrouillage. Il est également possible qu'une instruction avant, mais au sein de la même transaction (mais non identifié dans le graphe de blocage) verrouillé 1 des 2 ressources. Mais 1 des 2 déclarations dans l'impasse est définitivement impliqué dans le verrouillage de l'une des 2 ressources provoquant le blocage au moment où l'impasse a été enregistrée. Avant de faire tout ce qui précède, si cela vous sera utile si vous avez les graphiques Deadlock, vous pouvez tracer cela avec le Profiler ou les journaux SQL avec Trace Flag, mais le plus pratique est d'utiliser les événements SQL Server Extended fonctionnalité. Simplement en exécutant la requête ci-dessous vous pouvez récupérer les graphiques de blocage.

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 

Pour SQL Server 2008 et 2008 R2, utilisez cette requête.

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 
+0

Cela fait longtemps que j'ai regardé ce problème et que je n'ai plus accès à ces systèmes, donc je ne peux pas vraiment vérifier cette solution. Cela dit, merci de poster, je suis sûr que cela aidera quelqu'un parfois! – skimania