Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Blocage SQL avec opérations de sélection/mise à jour sur une table

Les deux requêtes provoquant le blocage sont le SELECT ci-dessous (process id="process3980de4558" ):

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

Et la UPDATE requête ci-dessous (process id="process386ed48188" ):

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

Le <resource-list> la section note le SELECT requête possédait un verrou exclusif (X) sur une page et essayait d'acquérir un verrou intentionnel partagé (IS) sur une autre page pendant qu'elle lisait des données. La UPDATE requête possédait déjà un verrou IS et essayait d'acquérir un verrou X sur une page pour effectuer la mise à jour.

Étant donné la jointure avec cette table :

...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...

Le SELECT la requête possède déjà un verrou exclusif. Cela signifie probablement qu'il fait partie d'une transaction plus importante qui a déjà effectué une UPDATE dans une requête préalable. Les verrous des requêtes précédentes seront conservés pour préserver l'intégrité des données pendant la transaction (selon le niveau d'isolement des transactions ).

La UPDATE la requête doit lire la table tbl_Ref_Attr_Prod_team . Il acquiert des verrous partagés par intention sur les pages et les lignes lors de la lecture des données. Lorsque la UPDATE requête trouve les lignes correspondantes, elle tentera de convertir les verrous IS en verrous X. Les verrous IS ne sont pas compatibles avec les verrous X. Parce que le SELECT requête a déjà un verrou IS sur une ou plusieurs de ces pages, les requêtes se bloquent les unes avec les autres.

Une cause possible serait des index manquants sur tbl_Ref_Attr_Prod_team.prod_key . Sans index sur cette colonne, le UPDATE la requête analysera toutes les lignes de la table tbl_Ref_Attr_Prod_team .

Même si un index existe sur prod_key , s'il y a un petit nombre de lignes dans la table, SQL Server peut décider que les performances seraient meilleures si la requête analysait la table entière au lieu de rechercher l'index. L'enregistrement du plan de requête lorsque le blocage se produit vérifierait cette théorie.

Nous rencontrons régulièrement de petits blocages de table lors de la mise en place de nouvelles bases de données. Au départ, les tables sont minuscules et les balayages de table provoquent toutes sortes de blocages. Plus tard, lorsque les tables sont plus volumineuses, le coût calculé de l'analyse de la table dépasse le coût de la recherche de l'index, et les interblocages ne se produisent plus. Dans les environnements de test où le nombre de lignes est toujours petit, nous avons eu recours à FORESEEK et WITH INDEX conseils pour forcer les recherches d'index au lieu des analyses. Nous sommes impatients de pouvoir forcer les plans de requête via la fonctionnalité de magasin de requêtes de SQL Server 2016.