Présentation
Les bases de données relationnelles suivent les propriétés ACID dans la façon dont elles implémentent les transactions - Atomicité, Cohérence, Isolation et Durabilité. L'isolation est nécessaire pour garantir que plusieurs transactions ne peuvent pas modifier les données et laisser les résultats éventuels incohérents. Pour garantir que les opérations restent isolées, SQL Server applique des mécanismes de verrouillage.
Modes de verrouillage et hiérarchie
Le mécanisme de contrôle de la concurrence de SQL Server est impliqué. Pour optimiser les performances en termes d'attentes de verrouillage, de blocages, etc., vous devez prendre une décision en fonction du scénario spécifique.
Dans SQL Server, les verrous peuvent être détenus de différentes manières et à plusieurs niveaux de granularité. Les modes de verrouillage sont les moyens spécifiques de le faire, et leurs niveaux sont la hiérarchie de verrouillage.
La figure 1 montre les modes de verrouillage disponibles dans SQL Server pour le niveau d'isolation des transactions par défaut (READ COMMITTED) :
Présentation de l'escalade de verrouillage
SQL Server peut verrouiller des ressources à plusieurs niveaux. Cela dépend des actes les plus efficaces selon la nature de la charge de travail. Le tableau 1 montre les ressources qui peuvent être verrouillées.
- Les verrous à un niveau plus précis (par exemple, les verrous au niveau de la ligne) permettent une plus grande simultanéité et moins de blocage.
- Les verrous à un niveau supérieur (par exemple, le verrouillage au niveau de la table) réduisent la simultanéité. Ils peuvent provoquer davantage de blocages, selon la durée de l'instruction réelle.
SQL Server choisit le niveau de verrouillage nécessaire en fonction de métriques internes.
Une escalade de verrou se produit lorsqu'un verrou est converti d'un niveau de granularité plus fin à un niveau plus grossier.
Par exemple, convertir un verrou de ligne en verrou de table (voir tableau 1).
Ressource | Description |
RID | L'identifiant de ligne utilisé pour verrouiller une seule ligne dans un tas. |
CLÉ | Le verrou de ligne dans un index utilisé pour protéger les plages de clés dans les transactions sérialisables. |
PAGE | La page de 8 kilo-octets (Ko) dans une base de données, telle que les pages de données ou d'index. |
ÉTENDUE | Le groupe contigu de huit pages, telles que des pages de données ou d'index. |
HoBT | Le tas ou arbre B. Le verrou protège un arbre B (index) ou les pages de données de tas dans une table qui n'a pas d'index clusterisé. |
TABLEAU | La table entière, y compris toutes les données et tous les index. |
FICHIER | Le fichier de base de données. |
CANDIDATURE | La ressource spécifiée par l'application. |
MÉTADONNÉES | Verrouillage des métadonnées. |
ALLOCATION_UNIT | L'unité d'allocation. |
BASE DE DONNÉES | L'intégralité de la base de données. |
La justification de l'escalade de verrouillage
Les verrous dans SQL Server peuvent être assez coûteux. Pour chaque verrou acquis par le gestionnaire de verrous, SQL Server doit réserver de la mémoire - 64 octets ou 128 octets. Le montant dépend si nous avons affaire à un système 32 bits ou 64 bits, respectivement.
À mesure que le nombre de verrous de ligne sur une table augmente, SQL Server doit acquérir de plus en plus de mémoire. Par conséquent, d'autres processus manquent de mémoire.
Il est logique de convertir les verrous de ligne et les verrous de page en un seul verrou au niveau de la table (objet). Cela se produit lorsque le nombre de verrous pour cette table dépasse 5 000.
La compromission se produit lorsque la table entière n'est plus disponible pour les autres sessions du processus de transaction.
Démonstration de l'escalade de verrouillage
Nous pouvons démontrer Lock Escalation en utilisant le code de la liste 1.
Commençons par décrire un peu le tableau. Production.ProduitsI est une table relativement petite contenant environ 7777 lignes. Les éléments de construction sont le même ensemble de 77 rangées dupliquées 101 fois. Le code de la liste 1 se compose de trois versions de la même instruction de mise à jour, chacune incluse dans une transaction.
-- Listing 1: Demonstrating Lock Escalation
-- Update very few rows
BEGIN TRAN
use TSQLV4
GO
UPDATE Production.ProductsI SET unitprice='100.00'
WHERE unitprice='18.00';
ROLLBACK
-- Update a large number of rows
BEGIN TRAN
use TSQLV4
GO
UPDATE Production.ProductsI SET unitprice='100.00'
WHERE unitprice>'18.00';
ROLLBACK
-- Update over 5000 rows
BEGIN TRAN
use TSQLV4
GO
UPDATE Production.ProductsI SET unitprice='100.00';
ROLLBACK
Pour plus de clarté, nous détaillerons le contenu du Listing 1.
Avant cela, observons Listing 2 - une requête pour afficher les verrous détenus dans la base de données TSQLV4.
Notre première action est d'exécuter le Listing 1a. Ensuite, nous utilisons le Listing 2 pour examiner comment le Lock Manager effectue le verrouillage dans le scénario. Nous exécutons la liste 1a sans émettre l'instruction de restauration. De cette façon, nous conservons les verrous suffisamment longtemps pour que la requête du Listing 2 puisse les capturer.
-- Listing 1a: Demonstrating Lock Escalation
-- Update very few rows
BEGIN TRAN
use TSQLV4
GO
UPDATE Production.ProductsI SET unitprice='100.00'
WHERE unitprice='18.00';
ROLLBACK
-- Listing 2: Displaying Locks Held in Database TSQLV4
USE TSQLV4
GO
SELECT
resource_type
, DB_NAME (resource_database_id) database_name
--, OBJECT_NAME(resource_associated_entity_id) resource_name
, request_mode
, request_type
, request_status
, request_reference_count
, request_session_id
, resource_associated_entity_id
, OBJECT_NAME(resource_associated_entity_id) [object_name] --small obj ids
, getuser.login_name
FROM sys.dm_tran_locks
CROSS APPLY dmv.dbo.getuser(request_session_id) as getuser
WHERE DB_NAME (resource_database_id)='TSQLV4';
Lorsque nous exécutons la requête de la liste 1a, puis vérifions les verrous à l'aide de la requête de la liste 2, SQL Server renvoie le résultat illustré à la figure 2.
404 lignes du tableau ont unitprice=’18.00’ . Le gestionnaire de verrous verrouille ces rangées avec les autres verrous de n'importe quel niveau nécessaire. Cela porte le nombre de lignes de la figure 2 à 467.
-- Listing 1b: Demonstrating Lock Escalation
-- Update a large number of rows
BEGIN TRAN
use TSQLV4
GO
UPDATE Production.ProductsI SET unitprice='100.00'
WHERE unitprice>'18.00';
ROLLBACK
Nous observons un comportement similaire lorsque nous exécutons la requête du Listing 1b. Cette fois, nous avons affaire à 4406 lignes. Il reflète le nombre de lignes sur la table Production.ProductI ayant un prix unitaire> 18,00.
-- Listing 1c: Demonstrating Lock Escalation
-- Update over 5000 rows
BEGIN TRAN
use TSQLV4
GO
UPDATE Production.ProductsI SET unitprice='100.00';
ROLLBACK
Lorsque nous allons plus loin et exécutons le code du Listing 1c, nous observons un comportement différent (voir Figure 4).
Le listing 1c tente de mettre à jour les 7777 lignes de la table Production.ProductI. SQL Server détermine que le verrouillage d'autant de lignes n'est plus efficace pour garantir l'isolement. Au lieu de cela, la table entière est verrouillée.
En savoir plus sur l'escalade de verrouillage
Le verrouillage de la table implique qu'aucune autre session ne peut modifier ses lignes pendant la durée de la transaction, ce qui peut arriver même lorsqu'une session bloquante ne manipule pas toutes les lignes de la table.
Il convient également de mentionner que d'autres facteurs peuvent affecter la façon dont les verrous sont acquis et remontés dans SQL Server. Il s'agit du niveau d'isolement configuré, de l'indexation et des indicateurs de trace.
Les indicateurs de suivi T1211 et T1224 peuvent s'appliquer pour désactiver entièrement l'escalade de verrouillage. L'escalade de verrous peut également être désactivée et activée pour une table spécifique avec le code suivant :
-- Listing 5: Disable and Enable Lock Escalation
ALTER TABLE Production.ProductsI SET (LOCK_ESCALATION=DISABLE);
ALTER TABLE Production.ProductsI SET (LOCK_ESCALATION=TABLE);
On peut vouloir le faire pour réduire le blocage associé au verrouillage de l'ensemble du tableau. En raison de l'impact sur la mémoire, il convient d'envisager une mesure temporaire.
Conclusion
SQL Server utilise Lock Escalation pour contrôler l'impact d'un verrouillage plus granulaire sur les ressources du serveur. Pour afficher le chemin des occurrences de ces verrous - verrous de ligne, verrous de page, verrous d'objet, etc. - interrogez la vue de gestion dynamique sys.dm_tran_locks. Il fournit de nombreuses informations sur le verrouillage, en plus de Lock Escalation.
Bien qu'il soit possible de manipuler le comportement du Lock Manager, il est essentiel de le faire avec beaucoup de soin. Il est également crucial de connaître l'impact précis sur les performances de tout effort visant à effectuer de telles modifications.
Références
- Korotkevitch, D., 2016. Éléments internes de Pro SQL Server. Floride :Dmitri Korotkevitch
- Scénarios de verrouillage à l'aide de Sys.dm_tran_locks
- Guide sur le verrouillage des transactions et la gestion des versions des lignes