J'ai trois tables d'index de colonnes en cluster (CCI) dans SQL Server 2016. Toutes ces CCI sont dans le même schéma de partitionnement, basé sur l'ID du locataire. Dernièrement, et de manière incohérente, je reçois des blocages sur les instructions de sélection simples des jointures à ces tables. Exemple de requête bloquant:
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
Message d'erreur:
La transaction (ID de processus 56) a été bloquée sur des ressources d'objet en attente génériques avec un autre processus et a été choisie comme victime de blocage. Relancez la transaction.
Des indices:
Notre version PROD:
Microsoft SQL Server 2016 (SP2-CU5) (KB4475776) - 13.0.5264.1 (X64) 10 janvier 2019 18:51:38 Copyright (c) Microsoft Corporation Enterprise Edition (64 bits) sur Windows Server 2012 R2 Standard 6.3 (Build 9600 :) (Hyperviseur)
Comment empêcher les blocages sur cette requête?
Puisque vous êtes sur SQL Server 2016, il convient de mentionner qu'il existe au moins un correctif de bogue public pour les blocages parallèles impliquant des index columnstore:
(merci à Denis Rubashkin pour avoir fourni le lien initialement)
Cela a été publié dans le cadre du SP1 CU7. Si vous n'êtes pas à la hauteur de ce CU, vous devriez essayer. Ce correctif serait également inclus dans SP2 (l'un des CU).
En général, les deux approches pour corriger les blocages de parallélisme intra-requête:
MAXDOP
, etc.) - ceci est couvert dans le autre réponse par Thomas CostersAvez-vous vérifié le blog suivant sur Deadlocks de threads parallèles intra-requête
La ressource SyncPoint
indique l'utilisation d'un événement d'échange si je ne me trompe pas.
En regardant les participants de votre impasse, vous pouvez voir qu'ils proviennent tous du même spid (55) et du même lot (0), mais utilisent des threads différents. Cela indique qu'ils font tous partie de la même requête parallèle et est confirmé par le fait que vous ne recevez aucun blocage à chaque fois que vous exécutez la requête avec MAXDOP 1
. Dans le cas des interblocages de threads parallèles intra-requête, les threads d'une seule requête finiront par se bloquer entre eux en attendant des objets de synchronisation, SyncPoints dans votre cas.
La dernière fois que j'ai été témoin de ce type de comportement, j'ai pu optimiser davantage la requête et empêcher ainsi la requête d'utiliser un plan d'exécution parallèle. Je soupçonne que vous avez fait la même chose en limitant votre jeu de résultats à 32 enregistrements ou en utilisant un index différent.
Une autre option serait d'ajouter MAXDOP 1
à votre requête, mais pas un grand fan de cette option.
Mais avant de jouer avec ces deux options, vérifiez d'abord si vous êtes sur le dernier SP/CU.