Come impedire i deadlock di Columnstore partizionati su SELECT


10

Ho tre tabelle CCI (Clustered Columnstore Index) in SQL Server 2016. Tutti questi CCI si trovano nello stesso schema di partizionamento, basato sull'ID tenant. Ultimamente e incoerentemente, sto ottenendo deadlock su semplici istruzioni select dai join a queste tabelle. Query di esempio che blocca i deadlock:

SELECT  TOP 33 r.tenantid
FROM    Table_r r
        INNER JOIN Table_cm cm ON r.MyKey=cm.MyKey 
        INNER JOIN Table_pe pe ON r.MyKey=pe.MyKey 
WHERE   r.TenantId = 69
        AND pe.TenantId = 69
        AND cm.TenantId = 69

Messaggio di errore:

La transazione (ID processo 56) è stata bloccata su risorse generiche di oggetti attendibili con un altro processo ed è stata scelta come vittima del deadlock. Rieseguire la transazione.

indizi:

  • Se la query utilizza un altro indice oltre a CCI, non si blocca.
  • Se rimuovo due dei tre filtri tenantid, non si blocca.
  • Se seleziono la parte superiore 32 o inferiore, non si blocca.
  • Se aggiungo OPTION (MAXDOP 1) non si blocca.
  • Posso riproporlo nella mia replica PROD criptata, nella PROD READ-ONLY Secondary e nella stessa PROD.
  • Non riesco a riprodurre questo comportamento in DEV o INT.
  • Si blocca ancora se aggiungo WITH (NOLOCK) a tutti e 3 i join di tabella
  • La query si blocca da sola. Si bloccherà quando non ci sono altri processi attivi.
  • I piani di query senza parallelismo non si bloccano

Deadlock xml qui

La nostra versione PROD:

Microsoft SQL Server 2016 (SP2-CU5) (KB4475776) - 13.0.5264.1 (X64) 10 gennaio 2019 18:51:38 Copyright (c) Microsoft Corporation Enterprise Edition (64 bit) su Windows Server 2012 R2 Standard 6.3 (Build 9600 :) (Hypervisor)

Come posso evitare deadlock su questa query?

Risposte:


8

Dato che sei su SQL Server 2016, vale la pena ricordare che esiste almeno una correzione di bug pubblica per deadlock paralleli che coinvolgono gli indici columnstore:

FIX: si verifica un deadlock quando si esegue una query parallela su un indice columnstore cluster in SQL Server 2016 e 2017

(grazie a Denis Rubashkin per aver fornito il link inizialmente)

Questo è stato rilasciato come parte di SP1 CU7. Se non sei all'altezza di quella CU, dovresti provare. Questa correzione sarebbe inclusa anche in SP2 (una qualsiasi delle CU).

In generale, i due approcci per correggere i deadlock del parallelismo all'interno delle query:

  • evitare il parallelismo (ottimizzando la query in modo che non diventi parallela, usando un MAXDOPsuggerimento, ecc.) - questo è trattato nell'altra risposta di Thomas Costers
  • applicare l'ultimo service pack / aggiornamenti cumulativi a SQL Server

2

Hai controllato il seguente blog sui deadlock di thread paralleli intra-query

La SyncPointrisorsa indica l'uso di un evento di scambio se non sbaglio.
Guardando i partecipanti al tuo deadlock puoi vedere che provengono tutti dallo stesso spid (55) e batch (0), ma usano thread diversi. Ciò indica che fanno tutti parte della stessa query parallela ed è confermato dal fatto che non si ricevono deadlock ogni volta che si esegue la query MAXDOP 1. Nel caso di deadlock di thread paralleli intra-query, i thread di una singola query finiranno per bloccarsi a vicenda in attesa di oggetti di sincronizzazione, SyncPoints nel tuo caso.

L'ultima volta, quando ho assistito a questo tipo di comportamento, sono stato in grado di ottimizzare ulteriormente la query e quindi impedire alla query di utilizzare un piano di esecuzione parallelo. Sospetto che tu abbia fatto la stessa cosa limitando il tuo set di risultati a 32 record o usando un indice diverso.
Un'altra opzione sarebbe quella di aggiungere MAXDOP 1alla tua query, anche se non è un grande fan di questa opzione.

Ma prima di armeggiare con queste due opzioni, controlla se sei sull'ultimo SP / CU.

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.