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

L'anatomie des blocages SQL Server et les meilleurs moyens de les éviter

Les professionnels des bases de données sont régulièrement confrontés à des problèmes de performances des bases de données, tels qu'une indexation incorrecte et un code mal écrit dans les instances SQL de production. Supposons que vous ayez mis à jour une transaction et que SQL Server ait signalé le message de blocage suivant. Pour les administrateurs de base de données qui débutent, cela peut être un choc.

Dans cet article, nous allons explorer les blocages SQL Server et les meilleurs moyens de les éviter.

Qu'est-ce qu'un blocage SQL Server ?

SQL Server est une base de données hautement transactionnelle. Par exemple, supposons que vous preniez en charge la base de données d'un portail d'achat en ligne sur lequel vous recevez de nouvelles commandes de clients 24 heures sur 24. Plusieurs utilisateurs effectuent probablement la même activité en même temps. Dans ce cas, votre base de données doit respecter les propriétés Atomicité, Cohérence, Isolation, Durabilité (ACID) afin d'être cohérente, fiable et de protéger l'intégrité des données.

L'image ci-dessous décrit les propriétés ACID dans une base de données relationnelle.

Pour suivre les propriétés ACID, SQL Server utilise des mécanismes de verrouillage, des contraintes et une journalisation en écriture anticipée. Les différents types de verrous incluent :le verrou exclusif (X), le verrou partagé (S), le verrou de mise à jour (U), le verrou d'intention (I), le verrou de schéma (SCH) et le verrou de mise à jour en bloc (BU). Ces verrous peuvent être acquis au niveau de la clé, de la table, de la ligne, de la page et de la base de données.

Supposons que vous ayez deux utilisateurs, John et Peter, connectés à la base de données clients.

  • John souhaite mettre à jour les enregistrements du client ayant [customerid] 1.
  • En même temps, Peter veut récupérer la valeur pour le client ayant [customerid] 1.

Dans ce cas, SQL Server utilise les verrous suivants pour John et Peter.

Verrous pour John

  • Il faut un verrou exclusif d'intention (IX) sur la table et la page client qui contient l'enregistrement.
  • Il prend en outre un verrou exclusif (X) sur la ligne que John souhaite mettre à jour. Il empêche tout autre utilisateur de modifier les données de ligne jusqu'à ce que le processus A libère son verrou.

Serrures pour Peter

  • Il acquiert un verrou partagé d'intention (IS) sur la table client et la page qui contient l'enregistrement conformément à la clause where.
  • Il essaie de prendre un verrou partagé pour lire la ligne. Cette ligne a déjà un verrou exclusif pour John.

Dans ce cas, Peter doit attendre que John termine son travail et libère le verrou exclusif. Cette situation est connue sous le nom de blocage.

Maintenant, supposons que dans un autre scénario, John et Peter aient les verrous suivants.

  • John a un verrou exclusif sur la table client pour l'ID client 1.
  • Peter a un verrou exclusif sur la table des commandes pour l'identifiant client 1.
  • John a besoin d'un verrou exclusif sur la table des commandes pour terminer sa transaction. Peter a déjà un verrou exclusif sur la table des commandes.
  • Peter a besoin d'un verrou exclusif sur la table des clients pour terminer sa transaction. John a déjà un verrou exclusif sur la table des clients.

Dans ce cas, aucune des transactions ne peut se poursuivre car chaque transaction nécessite une ressource détenue par l'autre transaction. Cette situation est connue sous le nom de blocage SQL Server.

Mécanismes de surveillance des interblocages SQL Server

SQL Server surveille périodiquement les situations de blocage à l'aide du thread de surveillance des blocages. Cela vérifie les processus impliqués dans un blocage et identifie si une session est devenue une victime de blocage. Il utilise un mécanisme interne pour identifier le processus victime du blocage. Par défaut, la transaction avec le moins de ressources requises pour la restauration est considérée comme une victime.

SQL Server tue la session victime afin qu'une autre session puisse acquérir le verrou requis pour terminer sa transaction. Par défaut, SQL Server vérifie la situation de blocage toutes les 5 secondes à l'aide du moniteur de blocage. S'il détecte un blocage, il peut réduire la fréquence de 5 secondes à 100 millisecondes en fonction de l'occurrence du blocage. Il réinitialise à nouveau le thread de surveillance à 5 secondes si des blocages fréquents ne se produisent pas.

Une fois que SQL Server tue un processus en tant que victime d'un blocage, vous recevrez le message suivant. Dans cette session, le processus ID 69 a été victime d'un blocage.

Les impacts de l'utilisation des instructions de priorité d'interblocage SQL Server

Par défaut, SQL Server marque la transaction avec la restauration la moins coûteuse comme victime d'un blocage. Les utilisateurs peuvent définir la priorité de blocage dans une transaction à l'aide de l'instruction DEADLOCK_PRIORITY.

SET DEADLOCK_PRIORITY

Il utilise les arguments suivants :

  • Faible :cela équivaut à la priorité d'interblocage -5
  • Normal :il s'agit de la priorité d'interblocage par défaut 0
  • Élevé :il s'agit de la priorité d'interblocage la plus élevée 5.

Nous pouvons également définir des valeurs numériques pour la priorité de blocage de -10 à 10 (total 21 valeurs).

Examinons quelques exemples d'énoncés de priorité de blocage.

Exemple 1 :

Session 1 avec priorité d'interblocage :Normale (0)> Session 2 avec priorité d'interblocage :Basse (-5)

Victime de l'impasse :  Séance 2

Exemple 2 :

Session 1 avec priorité blocage :Normal (0)

Victime de l'impasse :  Séance 1

Exemple 3

Session 1 avec priorité d'interblocage :-3> Session 2 avec priorité d'interblocage :-7

Exemple 4 :

Session 1 avec priorité blocage :-5

Victime de l'impasse :  Séance 1

Interblocages SQL Server à l'aide de graphes d'interblocage

Un graphique d'interblocage est une représentation visuelle des processus d'interblocage, de leurs verrous et de la victime de l'interblocage. Nous pouvons activer les indicateurs de trace 1204 et 1222 pour capturer des informations détaillées sur les interblocages dans un format XML et graphique. Nous pouvons utiliser l'événement étendu system_health par défaut pour obtenir les détails de l'interblocage. Un moyen rapide et facile d'interpréter le blocage consiste à utiliser un graphique de blocage. Simulons une condition de blocage et visualisons son graphique de blocage correspondant.

Pour cette démonstration, nous avons créé la table Client et Commandes et inséré quelques exemples d'enregistrements.

CREATE TABLE Customer (ID INT IDENTITY(1,1), CustomerName VARCHAR(20)) GO CREATE TABLE Orders (OrderID INT IDENTITY(1,1), ProductName VARCHAR(50)) GO INSERT INTO Customer(CustomerName) VALUES ('Rajendra') Go 100 S INSERT INTO Orders(ProductName) VALUES ('Laptop') Go 100

Ensuite, nous avons ouvert une nouvelle fenêtre de requête et activé l'indicateur de trace globalement.

Traceur DBCC(1222,-1)

Une fois que nous avons activé l'indicateur de trace de blocage, nous avons démarré deux sessions et exécuté la requête dans l'ordre ci-dessous :

  • La première session démarre une transaction pour mettre à jour la table des clients pour l'ID client 1.
  • La deuxième session démarre une transaction pour mettre à jour la table des commandes pour l'ID de commande 10.
  • La première session tente de mettre à jour la table des commandes pour le même ID de commande 10. La deuxième session verrouille déjà cette ligne. La session 1 est bloquée en raison des verrous détenus par la session 2.
  • Maintenant, pour la session 2, nous voulons mettre à jour la table des clients pour l'ID client 1. Cela génère une situation de blocage dans laquelle les sessions ID 63 et ID 65 ne peuvent pas progresser.

Dans cet exemple, SQL Server choisit une victime de blocage (ID de session 65) et tue la transaction. Récupérons le graphique de blocage de la session d'événements étendus system_health.

SELECT XEvent.query('(event/data/value/deadlock)[1]') AS DeadlockGraph FROM ( SELECT XEvent.query('.') AS XEvent FROM ( SELECT CAST(target_data AS XML) AS TargetData FROM sys.dm_xe_session_targets st INNER JOIN sys.dm_xe_sessions s ON s.address = st.event_session_address WHERE s.NAME = ‘system_health’ AND st.target_name = ‘ring_buffer’ ) AS Data CROSS APPLY TargetData.nodes('RingBufferTarget/event[@name="xml_deadlock_report"] ') AS XEventData(XEvent) ) AS source;

Cette requête nous donne une impasse XML qui nécessite un DBA expérimenté pour interpréter les informations.

Nous enregistrons ce fichier XML de blocage en utilisant l'extension .XDL et lorsque nous ouvrons le fichier XDL dans SSMS, nous obtenons le graphique de blocage illustré ci-dessous.

Ce graphique d'interblocage fournit les informations suivantes :

  • Nœuds de processus :  Dans l'ovale, vous obtenez des informations relatives au processus.
  • Nœuds de ressources :  Les nœuds de ressources (boîte carrée) fournissent des informations sur les objets impliqués dans les transactions avec les verrous. Dans cet exemple, il affiche les verrous RID car nous n'avons aucun index pour les deux tables.
  • Avantages :  Une arête relie le nœud de processus et le nœud de ressource. Il affiche le propriétaire de la ressource et le mode de verrouillage de la demande.

Il représente une victime d'impasse en barrant l'ovale dans le graphique d'impasse.

Vous pouvez capturer les informations d'interblocage SQL Server des manières suivantes :

  • Profilateur SQL Server
  • Événements étendus SQL Server
  • Journaux d'erreurs SQL Server
  • Traces par défaut dans SQL Server

5 types de blocages dans SQL Server

1) Blocage de recherche de signet

La recherche de signet est un blocage courant dans SQL Server. Cela se produit en raison d'un conflit entre l'instruction select et les instructions DML (insert, update et delete). Habituellement, SQL Server choisit l'instruction select comme victime d'un interblocage car elle ne provoque pas de modifications de données et la restauration est rapide. Pour éviter la recherche de signet, vous pouvez utiliser un index de couverture. Vous pouvez également utiliser un indicateur de requête NOLOCK dans les instructions de sélection, mais il lit les données non validées.

2) Blocage de l'analyse de distance

Parfois, nous utilisons un niveau d'isolation SERIALIZABLE au niveau du serveur ou au niveau de la session. Il s'agit d'un niveau d'isolement restrictif pour le contrôle de la concurrence et peut créer des verrous d'analyse de plage au lieu de verrous au niveau de la page ou de la ligne. Dans le niveau d'isolement SERIALIZABLE, les utilisateurs ne peuvent pas lire les données si elles sont modifiées mais attendent d'être validées dans une transaction. De même, si une transaction lit des données, une autre transaction ne peut pas les modifier. Il fournit la simultanéité la plus faible, nous devons donc utiliser ce niveau d'isolement dans les exigences d'application spécifiques.

3) Blocage de contraintes en cascade

SQL Server utilise la relation parent-enfant entre les tables à l'aide des contraintes de clé étrangère. Dans ce scénario, si nous mettons à jour ou supprimons un enregistrement de la table parent, il prend les verrous nécessaires sur la table enfant pour empêcher les enregistrements orphelins. Pour éliminer ces interblocages, vous devez toujours modifier d'abord les données d'une table enfant, suivies des données parent. Vous pouvez également travailler directement avec la table parent à l'aide des options DELETE CASCADE ou UPDATE CASCADE. Vous devez également créer des index appropriés sur les colonnes de clé étrangère.

4) Blocage du parallélisme intra-requête

Une fois qu'un utilisateur envoie une requête au moteur de requête SQL, l'optimiseur de requête élabore un plan d'exécution optimisé. Il peut exécuter la requête dans un ordre sériel ou parallèle en fonction du coût de la requête, du degré maximal de parallélisme (MAXDOP) et du seuil de coût pour le parallélisme.

En mode parallélisme, SQL Server affecte plusieurs threads. Parfois, pour une grande requête en mode parallélisme, ces threads commencent à se bloquer. Finalement, cela se transforme en impasses. Dans ce cas, vous devez revoir le plan d'exécution et votre seuil MAXDOP et de coût pour les configurations de parallélisme. Vous pouvez également spécifier le MAXDOP au niveau de la session pour résoudre le scénario de blocage.

5) Inverser l'interblocage de l'ordre des objets

Dans ce type de blocage, plusieurs transactions accèdent aux objets dans un ordre différent dans le T-SQL. Cela provoque un blocage parmi les ressources pour chaque session et le convertit en un blocage. Vous souhaitez toujours accéder aux objets dans un ordre logique afin d'éviter une situation de blocage.

Méthodes utiles pour éviter et minimiser les blocages SQL Server

  • Essayez d'effectuer des transactions courtes ; cela évitera de détenir des verrous dans une transaction pendant une longue période.
  • Accéder aux objets d'une manière logique similaire dans plusieurs transactions.
  • Créez un index de couverture pour réduire la possibilité d'un blocage.
  • Créez des index correspondant aux colonnes de clé étrangère. De cette façon, vous pouvez éliminer les blocages dus à l'intégrité référentielle en cascade.
  • Définissez les priorités d'interblocage à l'aide de la variable de session SET DEADLOCK_PRIORITY. Si vous définissez la priorité d'interblocage, SQL Server tue la session avec la priorité d'interblocage la plus basse.
  • Utilisez la gestion des erreurs à l'aide des blocs try-catch. Vous pouvez intercepter l'erreur d'interblocage et réexécuter la transaction en cas de victime d'interblocage.
  • Modifiez le niveau d'isolement sur READ COMMITTED SNAPSHOT ISOLATION ou SNAPSHOT ISOLATION. Cela modifie le mécanisme de verrouillage de SQL Server. Cependant, vous devez être prudent lorsque vous modifiez le niveau d'isolement, car cela pourrait avoir un impact négatif sur d'autres requêtes.

Considérations sur les interblocages de SQL Server

Les interblocages sont un mécanisme naturel dans SQL Server pour éviter que la session ne maintienne des verrous et n'attende d'autres ressources. Vous devez capturer les requêtes bloquées et les optimiser afin qu'elles n'entrent pas en conflit les unes avec les autres. Il est important de capturer le verrou pendant une courte période et de le libérer, afin que d'autres requêtes puissent l'utiliser efficacement.

Les interblocages SQL Server se produisent, et bien que SQL Server gère en interne les situations d'interblocage, vous devez essayer de les minimiser autant que possible. Certaines des meilleures façons d'éliminer les blocages consistent à créer un index, à appliquer des modifications au code de l'application ou à inspecter attentivement les ressources dans un graphique de blocage. Pour plus de conseils sur la façon d'éviter les blocages SQL, consultez notre article : Éviter les blocages SQL avec le réglage des requêtes.