Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Deadlock SQL con operazioni di selezione/aggiornamento su una tabella

Le due query che causano il deadlock sono SELECT sotto (process id="process3980de4558" ):

select @existing = team_it_cube_attr_05 from tbl_Ref_Attr_Prod_Team where prod_id = @rec_key

E il UPDATE query di seguito (process id="process386ed48188" ):

UPDATE D
SET D.team_rss_attr_01 = LEFT(S.mkt_prodchar_13,25)...

Il <resource-list> la sezione nota il SELECT la query possedeva un blocco esclusivo (X) su una pagina e stava tentando di acquisire un blocco condiviso (IS) su un'altra pagina mentre stava leggendo i dati. Il UPDATE la query possedeva già un blocco IS e stava cercando di acquisire un blocco X su una pagina per eseguire l'aggiornamento.

Dato il join su questa tabella:

...from tbl_Ref_Attr_Prod_Team where prod_id = @rec_key...
...INNER JOIN tbl_Ref_Attr_Prod_Team D ON D.prod_key=P.prod_key...

Il SELECT la query possiede già un blocco esclusivo. Questo probabilmente significa che fa parte di una transazione più ampia che ha già eseguito un UPDATE in una domanda precedente. I blocchi delle query precedenti verranno mantenuti per preservare l'integrità dei dati durante la transazione (a seconda di livello di isolamento delle transazioni ).

Il UPDATE la query deve leggere la tabella tbl_Ref_Attr_Prod_team . Acquisisce blocchi con intento condiviso su pagine e righe durante la lettura dei dati. Quando il UPDATE query trova le righe corrispondenti, tenterà di convertire i blocchi IS in blocchi X. I blocchi IS non sono compatibili con i blocchi X. Perché il SELECT la query ha già un blocco IS su una o più di quelle pagine, le query si bloccano tra loro.

Una possibile causa potrebbe essere la mancanza di indici su tbl_Ref_Attr_Prod_team.prod_key . Senza un indice su questa colonna, UPDATE la query eseguirà la scansione di tutte le righe della tabella tbl_Ref_Attr_Prod_team .

Anche se esiste un indice su prod_key , se nella tabella è presente un numero ridotto di righe, SQL Server potrebbe decidere che le prestazioni sarebbero migliori se la query analizzasse l'intera tabella anziché cercare l'indice. La registrazione del piano di query quando si verifica il deadlock verificherebbe questa teoria.

Incontriamo regolarmente piccoli deadlock delle tabelle durante lo staging di nuovi database. Inizialmente, le tabelle sono minuscole e le scansioni delle tabelle causano tutti i tipi di deadlock. Successivamente, quando le tabelle sono più grandi, il costo calcolato della scansione della tabella supera il costo della ricerca dell'indice e i deadlock non si verificano più. Negli ambienti di test in cui il numero di righe è sempre piccolo, abbiamo utilizzato FORESEEK e WITH INDEX suggerimenti per forzare le ricerche sull'indice invece delle scansioni. Non vediamo l'ora di poter forzare i piani di query tramite la funzionalità di archiviazione query di SQL Server 2016.