Wenn ein Deadlock eines Parallelism Exchange-Ereignisses ohne Opfer ist, ist es ein Problem?

10

Wir sehen viele dieser Intra-Query-Parallel-Thread-Deadlocks in unserer Produktionsumgebung (SQL Server 2012 SP2 - ja ... ich weiß ...). Wenn wir uns jedoch das Deadlock-XML ansehen, das über erweiterte Ereignisse erfasst wurde, Die Opferliste ist leer.

<victim-list />

Das Deadlocking scheint zwischen 4 Threads zu liegen, zwei mit dem WaitType="e_waitPipeNewRow"und zwei mit dem 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>

So:

  1. Die Opferliste ist leer
  2. Die Anwendung, die die Abfrage ausführt, macht keinen Fehler und schließt die Abfrage ab
  3. Soweit wir sehen können, gibt es kein offensichtliches Problem, außer dass das Diagramm erfasst wird

Ist dies etwas anderes als Lärm?

Bearbeiten: Dank Pauls Antwort kann ich sehen, wo das Problem wahrscheinlich auftritt, und scheint sich mit dem Tempdb-Überlauf von selbst zu lösen. Geben Sie hier die Bildbeschreibung ein

Mark Sinkinson
quelle

Antworten:

11

Es würde mich nicht wundern, wenn das Deadlock-Diagramm so aussieht, wenn ein parallele Deadlock innerhalb einer Abfrage durch einen Austauschverlust behoben wird (es gibt also kein Opfer außer der Leistung).

Sie können diese Theorie bestätigen, indem Sie Austauschverluste erfassen und sie dem Deadlock zuordnen (oder nicht).

Das Schreiben von Austauschpuffern in Tempdb , um einen Deadlock zu beheben, ist nicht ideal. Versuchen Sie, Sequenzen von auftragserhaltenden Vorgängen im Ausführungsplan zu eliminieren (z. B. auftragserhaltende Börsen, die einen parallelen Zusammenführungs-Join speisen). Es sei denn, es verursacht kein spürbares Leistungsproblem und Sie müssen sich um andere Dinge Sorgen machen.

Wird dieses Problem aus Interesse wahrscheinlich durch eine hohe Fragmentierung / veraltete Statistik verschärft?

Fragmentierung, nein. Veraltete Statistiken: nicht in einem bestimmten Sinne, den ich mir vorstellen kann, nein. Natürlich sind nicht repräsentative Statistiken im Allgemeinen selten eine gute Sache.

Das grundlegende Problem hierbei ist, dass Parallelität am besten funktioniert, wenn zwischen Threads so wenig Abhängigkeiten wie möglich bestehen. Die erhaltene Reihenfolge führt zu ziemlich unangenehmen Abhängigkeiten. Die Dinge können leicht durcheinander geraten, und die einzige Möglichkeit, den Stau zu beseitigen, besteht darin, eine Reihe von Zeilen zu verschütten, die beim Austausch mit Tempdb gehalten werden .

Paul White 9
quelle
-1

Um diese unkritischen Deadlocks "Selbstauflösung durch Verschütten" von wichtigeren Deadlocks zu unterscheiden, kann eine Suchsemantik auf die Xdl-Struktur angewendet werden.

Beispielausgabe

Der folgende SP funktioniert nicht sofort, da er von ufn_ExtractSubstringsByPattern () abhängt. Diese Methode kann jedoch durch etwas ersetzt werden, das die eindeutige Anzahl direkt zurückgibt.

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
crokusek
quelle