Se um conflito do Parallelism Exchange Event for sem vítimas, isso é um problema?

10

Estamos vendo muitos desses deadlocks de encadeamento paralelo entre consultas no nosso ambiente de produção (SQL Server 2012 SP2 - sim ... eu sei ...), no entanto, ao analisar o XML de deadlock que foi capturado por eventos estendidos, a lista de vítimas está vazia.

<victim-list />

O impasse parece estar entre 4 threads, dois com o WaitType="e_waitPipeNewRow"e dois com o 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>

Então:

  1. A lista de vítimas está vazia
  2. O aplicativo que está executando a consulta não erro e conclui a consulta
  3. Até onde podemos ver, não há problema óbvio, além de o gráfico ser capturado

Portanto, há algo com que se preocupar além do ruído?

Edit: Graças à resposta de Paul, posso ver onde o problema provavelmente ocorre e parece se resolver com o derramamento de tempdb. insira a descrição da imagem aqui

Mark Sinkinson
fonte

Respostas:

11

Eu não ficaria surpreso se esse for o aspecto do gráfico de deadlock quando um deadlock paralelo entre consultas for resolvido por um derramamento de troca (para que não haja vítima, exceto desempenho).

Você pode confirmar essa teoria capturando derramamentos de troca e combinando-os (ou não) com o impasse.

Gravar buffers de troca no tempdb para resolver um impasse não é o ideal. Procure eliminar sequências de operações de preservação de ordem no plano de execução (por exemplo, trocas de preservação de ordem que alimentam uma junção de mesclagem paralela). A menos que isso não esteja causando um problema perceptível de desempenho e você tenha outras preocupações.

Fora de interesse, é provável que esse problema seja exacerbado por altas estatísticas de fragmentação / desatualizado?

Fragmentação, não. Estatísticas desatualizadas: não em nenhum sentido específico que eu possa pensar, não. É claro que estatísticas não representativas raramente são boas em geral.

A questão fundamental aqui é que o paralelismo funciona melhor quando há o menor número possível de dependências entre os threads; ordenação preservada introduz dependências bastante desagradáveis. As coisas podem facilmente se complicar, e a única maneira de eliminar o impasse é derramar um monte de linhas mantidas em trocas no tempdb .

Paul White 9
fonte
-1

Para distinguir esses bloqueios não críticos e de "auto-resolução por derramamento" dos bloqueios mais importantes, algumas semânticas de pesquisa podem ser aplicadas à estrutura Xdl.

Saída de exemplo

O SP a seguir não funcionará imediatamente, pois depende de ufn_ExtractSubstringsByPattern (), no entanto, esse método pode ser substituído por algo que retorna a contagem distinta diretamente.

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
fonte