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

Notions de base et utilisation de l'indicateur NOLOCK dans SQL Server

L'idée principale du mécanisme de verrouillage de SQL Server est qu'il contrôle la cohérence des transactions. Selon ce principe, si un processus souhaite effectuer des opérations d'insertion, de suppression ou de mise à jour, le moteur SQL Server verrouille la ou les lignes et n'autorise pas un autre processus tant que la transaction n'est pas terminée. Dans certaines circonstances, ce mécanisme de verrouillage peut entraîner des problèmes de performances tels que des pressions de processus simultanées élevées. Ainsi, vous pouvez rencontrer des problèmes de blocage (Deadlock est un problème de concurrence dans lequel deux transactions veulent accéder simultanément aux mêmes données) dans votre base de données. Dans cet article, nous allons nous concentrer sur la façon d'éviter les problèmes de verrouillage à l'aide de l'indice NOLOCK. Tout d'abord, apprenons les principaux éléments essentiels et les détails de la méthodologie de lecture sale, car l'indice NOLOCK peut provoquer une lecture sale.

Lecture grossière : Dans cette méthodologie de lecture, le processus de lecture lit les données non validées et le processus de lecture ne se soucie pas des transactions ouvertes, de sorte que les verrous n'entraînent aucun problème dans le processus de lecture. De ce fait, ce type de lecture réduit les problèmes de verrouillage. Cependant, la méthodologie de lecture incorrecte présente des avantages et des inconvénients, car la lecture incorrecte peut entraîner des problèmes d'incohérence dans le jeu de résultats de l'instruction SELECT. Comme déjà indiqué, ces ensembles de résultats peuvent inclure des données de transactions non validées, c'est pourquoi nous devons tenir compte de la lecture sale lorsque nous décidons de faire ce type de lecture. Nous ne pouvons pas être sûrs de l'exactitude des lignes que nous créons lors de la lecture incorrecte, car ces lignes peuvent être annulées. En revanche, ce type de lecture nous permet d'éviter les problèmes de verrouillage et d'augmenter les performances de SQL Server.

NOLOCK : Le niveau d'isolement par défaut de SQL Server est Read Committed et, dans ce niveau d'isolement, SQL Server n'autorise pas la lecture d'objets verrouillés qui sont verrouillés par des transactions non validées. De plus, ces objets verrouillés peuvent être modifiés en fonction de l'escalade de verrouillage.

Remarque :dans cet article sur le concept principal du verrouillage SQL Server, vous trouverez des détails sur le verrouillage et l'escalade des verrous.

Imaginez que vous avez deux utilisateurs de base de données et que ces utilisateurs souhaitent exécuter une opération de mise à jour et de sélection sur la base de données. Un premier utilisateur commence à mettre à jour une ligne particulière dans la table, puis l'autre utilisateur veut lire la même ligne. Ces deux utilisateurs exécutent les instructions de mise à jour et de sélection suivantes, illustrées dans l'image ci-dessous.

Dans ce cas, user2 attend au moins 10 secondes, puis la transaction sera annulée par user1, puis user2 peut lire la ligne verte car la ligne verrouillée sera libérée par user1. Il s'agit du comportement par défaut du niveau d'isolement SQL Server Read Committed.

Maintenant, nous allons démontrer ce cas dans SQL Server. Tout d'abord, nous allons créer la table FruitSales et ses lignes.

CREATE TABLE FruitSales
(Id INT IDENTITY (1,1)  PRIMARY KEY, [Name] Varchar(20) ,
SalesTotal Float)
GO

INSERT INTO FruitSales VALUES
('Apple',10) ,('Orange',8), ('Banana',2)

Dans cette étape, nous allons ouvrir deux fenêtres de requête SQL Server Management Studio et exécuter la requête user1, puis exécuter la requête user2.

	  ---USER1----

BEGIN TRAN 
UPDATE FruitSales SET SalesTotal =20 WHERE Id=2 
WAITFOR DELAY '00:00:10'
ROLLBACK TRANSACTION

	---USER2----
SET STATISTICS TIME ON
SELECT * FROM FruitSales WHERE Id=2

Comme vous pouvez le voir dans l'image ci-dessus, la deuxième requête attend jusqu'à l'annulation de la transaction user1.

Maintenant, nous allons discuter de l'indice NOLOCK et des détails d'utilisation. L'indicateur NOLOCK est l'indicateur de table le plus populaire utilisé par les développeurs et les administrateurs de bases de données pour éliminer les problèmes de verrouillage dans les bases de données SQL Server. À l'aide de l'indicateur de table NOLOCK, nous pouvons lire les objets verrouillés (ligne, page ou table) qui sont verrouillés par des transactions ouvertes. L'indicateur NOLOCK remplace le comportement par défaut de l'optimiseur de requête SQL Server afin que l'instruction select puisse lire les objets verrouillés.

Maintenant, nous allons ajouter l'indicateur NOLOCK à l'instruction de sélection de l'utilisateur2, puis démarrer la mise à jour de l'utilisateur1, puis exécuter l'instruction de sélection de l'utilisateur2.

---USER1----

BEGIN TRAN 
UPDATE FruitSales SET SalesTotal =20 WHERE Id=2 
WAITFOR DELAY '00:00:10'
ROLLBACK TRANSACTION

			---USER2----
SET STATISTICS TIME ON
SELECT * FROM FruitSales WITH(NOLOCK) WHERE Id=2

Dans cette étape, nous expliquerons comment affecter l'indicateur NOLOCK sur l'instruction select de l'utilisateur2. L'utilisateur1 exécute l'instruction mise à jour dans une transaction explicite, puis l'utilisateur2 exécute l'instruction de sélection et le jeu de résultats renvoie sans délai l'achèvement de la transaction. C'est l'idée principale de NOLOCK, il lit les objets verrouillés.

Maintenant, nous allons nous concentrer sur le jeu de résultats de l'instruction select. L'instruction select de l'utilisateur2 a récupéré la valeur SalesTotal 20, mais la valeur réelle de SalesTotal est toujours 8. Gardez à l'esprit que si vous utilisez l'indicateur de table NOLOCK dans votre instruction select, vous risquez d'être confronté à ce type de résultats de données inexacts.

Astuce : Le mot-clé « AVEC » est une fonctionnalité obsolète, Microsoft recommande donc de ne pas l'utiliser dans le développement de votre nouvelle base de données et de supprimer le mot-clé « AVEC » dans vos développements actuels. Vous pouvez trouver l'utilisation de l'indice NOLOCK sans le mot-clé « AVEC ».

---USER1----
BEGIN TRAN 
UPDATE FruitSales SET SalesTotal =20 WHERE Id=2 
WAITFOR DELAY '00:00:10'
ROLLBACK TRANSACTION
SELECT * FROM FruitSales WHERE Id=2

   --USER2---
SELECT * FROM FruitSales (NOLOCK) WHERE Id=2

De plus, l'indicateur de table READUNCOMMITTED est équivalent à l'indicateur NOLOCK et nous pouvons utiliser l'indicateur READUNCOMMITTED au lieu de l'indicateur NOLOCK.

SELECT * FROM FruitSales (READUNCOMMITTED) WHERE Id=2

Même ainsi, il existe un cas particulier concernant l'indice NOLOCK qui ne peut pas franchir la barrière de verrouillage. Si un processus modifie une table, l'indicateur NOLOCK ne peut pas surmonter ce type de verrou et ne peut pas poursuivre l'opération de lecture. La raison de ce problème est que l'indicateur NOLOCK acquiert le verrou Sch-S (stabilité du schéma) et que l'instruction ALTER TABLE acquiert le verrou SCH-M (modification du schéma), donc un conflit se produit.

Dans un premier temps, nous apprendrons l'Object_Id de la table FruitSales à l'aide de la requête suivante.

select OBJECT_ID('FruitSales')

Exécutez la requête user1 suivante, puis exécutez la requête user2. Par conséquent, la requête de l'utilisateur2 retardera l'achèvement du processus de modification de la table de l'utilisateur1.

--USER1---
BEGIN TRAN
ALTER TABLE FruitSales
ADD ColorofFruit varchar(200) 
WAITFOR DELAY '00:00:35
GO
COMMIT TRAN

   --USER2---
SELECT * FROM FruitSales (NOLOCK) WHERE Id=2

Ouvrez la nouvelle fenêtre de requête et exécutez la requête suivante. Cette requête permettra de connaître le type de verrou des requêtes user1 et user2.

SELECT Resource_type,
	 Resource_database_id,
	 Resource_description,
	 Resource_associated_entity_id,
	 Resource_lock_partition,
	 Request_mode,
	 Request_type,
	 Request_status,
	 Request_session_id,
	 Request_request_id,
	 Request_owner_type,
	 Request_owner_id,
	 Lock_owner_address
FROM sys.dm_tran_locks
where resource_associated_entity_id =647673355

Maintenant, nous allons vérifier la matrice de compatibilité des verrous pour l'interaction SCH-M et SCH-S. La matrice décrit que l'interaction SCH-M et SCH-S provoque un conflit.

Conclusion

Dans cet article, nous avons mentionné le processus de lecture sale et l'indice NOLOCK. L'utilisation de l'indice NOLOCK est une méthode efficace pour lire une page verrouillée, mais elle présente également des avantages et des inconvénients. Pour cette raison, vous devez considérer l'indice NOLOCK avant de l'utiliser.

Références

Guide de verrouillage des transactions SQL Server et de gestion des versions de ligne

Conseils (Transact-SQL) – Tableau

DÉFINIR LE NIVEAU D'ISOLEMENT DES TRANSACTIONS (Transact-SQL)