web-dev-qa-db-fra.com

Lecture du niveau d'isolement de capture instantanée contre capture instantanée

Est-ce que quelqu'un pourrait m'aider à comprendre quand utiliser le niveau d'isolement SNAPSHOT par rapport à SNAPSHOT READ COMMITTED dans SQL Server?

Je comprends que dans la plupart des cas, READ COMMITTED SNAPSHOT fonctionne, mais je ne sais pas quand aller pour l’isolation SNAPSHOT.

Merci

63
user173552

READ COMMITTED SNAPSHOT fait des lectures optimistes et des écritures pessimistes. En revanche, SNAPSHOT fait des lectures optimistes et des écritures optimistes.

Microsoft recommande READ COMMITTED SNAPSHOT pour la plupart des applications nécessitant un contrôle de version des lignes.

Lisez cet excellent article de Microsoft: Choix des niveaux d’isolement basés sur le dimensionnement des rangées . Il explique les avantages et les coûts des deux niveaux d’isolement. 

Et voici un document plus complet: http://msdn.Microsoft.com/en-us/library/ms345124(SQL.90).aspx

70
Bill Paetzke

 enter image description here [! [Tableau des niveaux d'isolement] [2]] [2]

Voir l'exemple ci-dessous:

Lire un instantané validé

Changer la propriété de la base de données comme ci-dessous

ALTER DATABASE SQLAuthority
SET READ_COMMITTED_SNAPSHOT ON WITH ROLLBACK IMMEDIATE
GO

Session 1

USE SQLAuthority
GO
BEGIN TRAN
UPDATE DemoTable
SET i = 4
WHERE i = 1

Session 2

USE SQLAuthority
GO
BEGIN TRAN
SELECT *
FROM   DemoTable
WHERE i = 1

Résultat - La requête de la session 2 affiche l'ancienne valeur (1, ONE) car la transaction en cours n'est PAS validée. C'est le moyen d'éviter de bloquer et de lire les données validées également.

Session 1

COMMIT

Session 2

USE SQLAuthority
GO
SELECT *
FROM   DemoTable
WHERE i = 1

Résultat - La requête de la session 2 n'affiche aucune ligne car celle-ci a été mise à jour pendant la session 1. Nous voyons donc à nouveau des données validées.

Niveau d'isolation d'instantané

Il s'agit du nouveau niveau d'isolation, disponible à partir de SQL Server 2005. Pour cette fonctionnalité, une modification est nécessaire dans l'application car elle doit utiliser un nouveau niveau d'isolation.

Modifier les paramètres de base de données en utilisant ci-dessous. Nous devons nous assurer qu'il n'y a pas de transaction dans la base de données.

ALTER DATABASE SQLAuthority SET AllOW_SNAPSHOT_ISOLATION ON

Maintenant, nous devons également modifier le niveau d’isolation de la connexion en utilisant les options ci-dessous.

Session 1

USE SQLAuthority
GO
BEGIN TRAN
UPDATE DemoTable
SET i = 10
WHERE i = 2

Session 2

SET TRANSACTION ISOLATION LEVEL SNAPSHOT
GO
USE SQLAuthority
GO
BEGIN TRAN
SELECT *
FROM   DemoTable
WHERE i = 2

Résultat: même si nous avons changé la valeur à 10, l'ancien enregistrement sera toujours affiché dans la session 2 (2, DEUX).

Maintenant, validons la transaction en session 1

Session 1

COMMIT

Revenons à la session 2 et exécutez à nouveau select.

Session 2

SELECT *
FROM   DemoTable
WHERE i = 2

Nous verrons toujours l'enregistrement car la session 2 a indiqué la transaction avec isolation de capture instantanée. À moins de compléter la transaction, nous ne verrons pas le dernier enregistrement.

Session 2

COMMIT
SELECT *
FROM   DemoTable
WHERE i = 2

Maintenant, nous ne devrions pas voir la ligne car elle est déjà mise à jour.

Voir: Autorité SQL , Safari Books Online

26
Akira Yamamoto

Aucune comparaison entre les instantanés et les instantanés lus validés n'est complète sans discussion de l'exception redoutée "conflit de mise à jour des instantanés" pouvant se produire dans Instantané, mais pas dans l'instantané lu validée. 

En résumé, l'isolation de capture instantanée récupère une capture instantanée de données validées au début d'une transaction, puis utilise un verrouillage optimiste pour les lectures et les écritures. Si, lors de la tentative de validation d'une transaction, il s'avère que quelque chose d'autre a modifié certaines de ces données, la base de données annule la totalité de la transaction et génère une erreur provoquant une exception de conflit de mise à jour de capture instantanée dans le code appelant. En effet, la version des données affectée par la transaction n'est pas la même à la fin de la transaction et au début.

Snapshot Read Committed ne souffre pas de ce problème car il utilise le verrouillage sur les écritures (écritures pessimistes) et obtient les informations de version de snapshot de toutes les données validées à la stat de chaque instruction

La possibilité de conflits de mise à jour des instantanés se produisant dans Snapshot et PAS Snapshot Read Committed est une différence extrêmement significative entre les deux.

3
user3444696

Toujours d'actualité, à commencer par les commentaires de Bill, j'ai lu davantage et pris des notes qui pourraient être utiles à quelqu'un d'autre.

Par défaut, les instructions simples (y compris "SELECT") fonctionnent sur des données "validées" (READ COMMITTED), la question est de savoir si elles attendent que les données soient "inactives" et empêchent les autres de travailler pendant la lecture.

Paramétrage par clic droit sur la base de données «Propriétés -> Options -> Divers»:

Accès simultané/blocage: la lecture de l'instantané validé est-elle activée [par défaut, doit être activé]:

  • Utilisez SNAPSHOT pour sélectionner (lire), n'attendez pas les autres et ne les bloquez pas.
  • Opération d'effets sans changement de code
  • ALTER DATABASE SET READ_COMMITTED_SNAPSHOT [ON | OFF]
  • SELECT nom, is_read_committed_snapshot_on FROM sys.databases

Cohérence: autoriser l'isolement d'instantanés [désactivés par défaut, discutables - OK désactivés]:

  • Autoriser le client à demander SNAPSHOT sur plusieurs instructions SQL (transactions).
  • Le code doit demander des instantanés «transactionnels» (comme SET TRANSACTION ...)
  • ALTER DATABASE SET ALLOW_SNAPSHOT_ISOLATION [ON | OFF]
  • SELECT nom, is_read_committed_snapshot_on FROM sys.databases

A la question: ce n'est pas un ou l'autre entre Read Instantané Commité et Autoriser Isolement Instantané. Il existe deux cas d'instantané, l'un ou l'autre pouvant être activé ou désactivé indépendamment, avec l'option Autoriser l'isolement d'un instantané étant un sujet plus avancé. Autoriser l’isolation d’instantané permet au code de franchir une étape supplémentaire en contrôlant le terrain d’instantané.

Le problème semble évident si vous pensez à une ligne: par défaut, le système n’a pas de copie. Le lecteur doit donc attendre si quelqu'un écrit et un écrivain doit attendre si quelqu'un lit, la ligne doit verrouiller tous les temps. L'activation de l'option «Est-ce que l'instantané lu est validé activé» active la base de données pour prendre en charge les «copies instantanées» afin d'éviter ces verrouillages.

Radoter...

À mon avis, «L’instantané lu validé sur» doit-il être «VRAI» pour toutes les bases de données MS SQLServer normales, et il s’agit d’une optimisation prématurée qui renvoie «FAUX» par défaut.

Cependant, on me dit que le verrouillage d'une ligne s'aggrave, non seulement parce que vous pouvez adresser plusieurs lignes sur plusieurs tables, mais aussi parce que dans SQL Server, les verrous de ligne sont implémentés à l'aide de verrous de niveau "bloc" (verrouillage de lignes aléatoires associées à la proximité du stockage). il existe un seuil permettant à plusieurs verrous de déclencher le verrouillage de la table - probablement des optimisations de performances "optimistes" au risque de blocage des problèmes dans les bases de données occupées.

0
Cris Mooney