Se un deadlock di un evento di scambio di parallelismo è senza vittime, è un problema?


10

Stiamo vedendo molti di questi deadlock di thread paralleli all'interno della query nel nostro ambiente di produzione (SQL Server 2012 SP2 - sì ... lo so ...), tuttavia quando osserviamo l'XML di deadlock che è stato acquisito tramite gli eventi estesi, l'elenco delle vittime è vuoto.

<victim-list />

Il deadlock sembra essere tra 4 thread, due con il WaitType="e_waitPipeNewRow"e due con il WaitType="e_waitPipeGetRow".

 <resource-list>
  <exchangeEvent id="Pipe13904cb620" WaitType="e_waitPipeNewRow" nodeId="19">
   <owner-list>
    <owner id="process4649868" />
   </owner-list>
   <waiter-list>
    <waiter id="process40eb498" />
   </waiter-list>
  </exchangeEvent>
  <exchangeEvent id="Pipe30670d480" WaitType="e_waitPipeNewRow" nodeId="21">
   <owner-list>
    <owner id="process368ecf8" />
   </owner-list>
   <waiter-list>
    <waiter id="process46a0cf8" />
   </waiter-list>
  </exchangeEvent>
  <exchangeEvent id="Pipe13904cb4e0" WaitType="e_waitPipeGetRow" nodeId="19">
   <owner-list>
    <owner id="process40eb498" />
   </owner-list>
   <waiter-list>
    <waiter id="process368ecf8" />
   </waiter-list>
  </exchangeEvent>
  <exchangeEvent id="Pipe4a106e060" WaitType="e_waitPipeGetRow" nodeId="21">
   <owner-list>
    <owner id="process46a0cf8" />
   </owner-list>
   <waiter-list>
    <waiter id="process4649868" />
   </waiter-list>
  </exchangeEvent>
 </resource-list>

Così:

  1. L'elenco delle vittime è vuoto
  2. L'applicazione che esegue la query non genera errori e completa la query
  3. Per quanto possiamo vedere, non vi è alcun problema evidente, a parte il fatto che il grafico viene acquisito

Pertanto, c'è qualcosa di cui preoccuparsi oltre al rumore?

Modifica: grazie alla risposta di Paul, posso vedere dove si verifica probabilmente il problema e sembra risolversi con la fuoriuscita di tempdb. inserisci qui la descrizione dell'immagine

Risposte:


11

Non sarei sorpreso se questo è il modo in cui appare il grafico del deadlock quando un deadlock parallelo all'interno della query viene risolto da una fuoriuscita di scambio (quindi non c'è vittima, tranne le prestazioni).

Potresti confermare questa teoria catturando gli sversamenti di scambio e abbinandoli (o meno) allo stallo.

Scrivere buffer di scambio su tempdb per risolvere un deadlock non è l'ideale. Cercare di eliminare le sequenze di operazioni di conservazione degli ordini nel piano di esecuzione (ad esempio scambi di conservazione degli ordini che alimentano un join di unione parallelo). A meno che non stia causando un notevole problema di prestazioni e non ci siano altre cose di cui preoccuparsi.

Per interesse, è probabile che questo problema sia esacerbato da elevate statistiche di frammentazione / obsolete?

Frammentazione, no. Statistiche obsolete: non in alcun senso specifico a cui riesco a pensare, no. Naturalmente le statistiche non rappresentative sono raramente una buona cosa in generale.

La questione fondamentale qui è che il parallelismo funziona meglio quando ci sono meno dipendenze possibili tra i thread; l'ordinamento conservato introduce dipendenze piuttosto brutte. Le cose possono essere facilmente gommate, e l'unico modo per cancellare il logjam è quello di rovesciare un gruppo di file trattenute negli scambi in tempdb .


-1

Per distinguere questi deadlock non critici, "auto-risolventi per sversamento" da deadlock più importanti, è possibile applicare alla struttura Xdl alcune semantiche di ricerca.

Esempio di output

Il seguente SP non funzionerà immediatamente poiché dipende da ufn_ExtractSubstringsByPattern () tuttavia tale metodo può essere sostituito con qualcosa che restituisce direttamente il conteggio distinto.

ALTER view [Common].[DeadLockRecentHistoryView]
as
/*---------------------------------------------------------------------------------------------------------------------
    Purpose:  List history of recent deadlock events

    Warning:  The XML processing may hit a recursion limit (100), suggest using "option (maxrecursion 10000)".

    Xdl File:
        The SSMS deadlock file format .XDL format (xml) has changed with later versions of SQL Server.  This version tested with 2012.

    Ring Buffer issues:
        https://connect.microsoft.com/SQLServer/feedback/details/754115/xevents-system-health-does-not-catch-all-deadlocks
        https://www.sqlskills.com/blogs/jonathan/why-i-hate-the-ring_buffer-target-in-extended-events/

    Links:
        http://www.sqlskills.com/blogs/jonathan/multi-victim-deadlocks/
        https://www.sqlskills.com/blogs/jonathan/graphically-viewing-extended-events-deadlock-graphs/
        http://www.mssqltips.com/sqlservertip/1234/capturing-sql-server-deadlock-information-in-xml-format/
        http://blogs.msdn.com/b/sqldatabasetalk/archive/2013/05/01/tracking-down-deadlocks-in-sql-database.aspx
        http://dba.stackexchange.com/questions/10644/deadlock-error-isnt-returning-the-deadlock-sql/10646#10646        

    Modified    By           Description
    ----------  -----------  ------------------------------------------------------------------------------------------
    2014.10.29  crokusek     From Internet, http://stackoverflow.com/questions/19817951
    2015.05.05  crokusek     Improve so that the output is consumable by SSMS 2012 as "Open .xdl file"                             
    2015.05.22  crokusek     Remove special character for the cast to Xml (like '&')
    2017.08.03  crokusek     Abandon ring-buffer approach and use event log files.  Filter out internal deadlocks.
    2018.07.16  crokusek     Added field(s) like ProbablyHandledBySpill to help identify non-critical deadlocks.
  ---------------------------------------------------------------------------------------------------------------------*/
with XmlDeadlockReports as
(
  select convert(xml, event_data) as EventData         
    from sys.fn_xe_file_target_read_file(N'system_health*.xel', NULL, NULL, NULL)      
   where substring(event_data, 1, 50) like '%"xml_deadlock_report"%'       
)
select top 10000
       EventData.value('(event/@timestamp)[1]', 'datetime2(7)') as CreatedUtc,
       --(select TimePst from Common.ufn_ConvertUtcToPst(EventData.value('(event/@timestamp)[1]', 'datetime2(7)'))) as CreatedPst,
       DistinctSpidCount,       
       HasExchangeEvent,
       IsVictimless,                  
       --
       -- If the deadlock contains Exchange Events and lists no victims, it probably occurred
       -- during execution of a single query that contained parallellism but got stuck due to 
       -- ordering issues.   /dba/197779
       -- 
       -- These will not raise an exception to the caller and will complete by spilling to tempdb
       -- however they may run much slower than they would without the spill(s).
       --
       convert(bit, iif(DistinctSpidCount = 1 and HasExchangeEvent = 1 and IsVictimless = 1, 1, 0)) as ProbablyHandledBySpill,
       len(et.XdlFileText) as LenXdlFile,
       eddl.XdlFile as XdlFile
  from XmlDeadlockReports
 cross apply 
     ( 
       select eventData.query('event/data/value/deadlock') as XdlFile 
     ) eddl
 cross apply 
     ( 
        select convert(nvarchar(max), eddl.XdlFile) as XdlFileText 
     ) as et
 cross apply 
     (
       select count(distinct Match) as DistinctSpidCount
         from common.ufn_ExtractSubstringsByPattern(et.XdlFileText, 'spid="%%"')
     ) spids
 cross apply
     (
       select convert(bit, iif(charindex('<exchangeEvent', et.XdlFileText) > 0, 1, 0)) as HasExchangeEvent,
              --
              convert(bit, iif(     charindex('<victim-list>', et.XdlFileText) = 0
                                and charindex('<victim-list/>', et.XdlFileText) > 0, 1, 0)) as IsVictimless
     ) as flags        
 order by CreatedUtc desc
GO
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.