ALLOW_SNAPSHOT_ISOLATION et READ_COMMITTED_SNAPSHOT

38

La plupart des forums et des exemples en ligne suggèrent toujours de les avoir tous les deux ALLOW_SNAPSHOT_ISOLATIONet READ_COMMITTED_SNAPSHOTsont activés lorsque quelqu'un pose un instantané, une version de ligne ou une question similaire.

Je suppose que le mot SNAPSHOT dans les deux contextes est un peu déroutant. J'ai pensé que, pour que le moteur de base de données utilise la gestion des versions de ligne au lieu de verrous pour le comportement par défaut de READ_COMMITTED, la base de données READ_COMMITTED_SNAPSHOTest définie sur ON, quel que soit le ALLOW_SNAPSHOT_ISOLATIONparamètre défini.

Le ALLOW_SNAPSHOT_ISOLATIONréglage est réglé sur ON uniquement pour permettre l' isolement d'instantané lors du démarrage d' une transaction (par exemple SET TRANSACTION SNAPSHOT ISOLEMENT DE NIVEAU) quel que soit de READ_COMMITTED_SNAPSHOTréglage.

La seule raison pour laquelle ces deux paramètres sont définis sur ON est lorsqu'il est nécessaire de disposer de la version de ligne READ COMMITTED et de l' isolation de capture instantanée.

Ma question est la suivante: ma compréhension est-elle incorrecte d'une manière ou d'une autre? Et que ces deux paramètres doivent toujours être sur ON (en particulier pour la gestion des versions de lignes READ COMMITTED)?

Travis
la source

Réponses:

25

Votre compréhension est correcte. Cela devient un peu déroutant.

Kim Tripp (l'un des programmeurs de SQL Server et partie intégrante de SQLSkills) décrit exactement ce que vous avez déclaré dans les vidéos MCM sur Snapshot Isolation . Fast fwd à 41:45 dans la vidéo pour arriver à la partie où elle répond à votre question.

Si vous utilisez ALLOW_SNAPSHOT_ISOLATIONassurez-vous que vous utilisez SET TRANSACTION ISOLATION LEVEL SNAPSHOTdans votre code, sinon vous n'obtiendrez aucun des avantages.

Si vous définissez SET READ_COMMITTED_SNAPSHOT ON, alors il n'est pas nécessaire de modifier le code. MS SQL Server applique automatiquement l'isolation de capture instantanée pour cette table.

Je n'ai pas testé pour voir ce qui se passe si vous demandez un niveau d'isolement différent dans votre code. Je suppose que cela écrasera cette option, mais le testera d'abord.

Un coup d'œil sur la surcharge de performances avec l’isolation d’instantané.

Bon article sur la manière dont l'isolement d'instantané peut modifier le comportement attendu de votre application . Il montre des exemples montrant comment une instruction update et une instruction select peuvent renvoyer des résultats totalement différents et inattendus.

Ali Razeghi
la source
Merci pour le lien. Comme d’autres BOL, elle a discuté de ces deux paramètres indépendamment et collectivement (c’est là que cela devient un peu déroutant ou peut-être que je le pense trop). J'ai dû le tester pour mieux comprendre.
Travis
4
C'est une excellente réponse et je voudrais seulement clarifier quelques points. Premièrement, si vous ne faites que numériser la vidéo, commencez à 23h18 et à 41h45. Le début du temps ajoute plus de détails. Bien que Kim mentionne une réponse à la question initiale, il est toujours nécessaire de modifier le code si vous utilisez les deux. Read_Committed_Snapshot est une isolation au niveau de l'instruction, autrement dit ne s'applique qu'à l'instruction en cours d'exécution. Allow_Snapshot_Isolation est une isolation au niveau de la transaction, comprise entre Begin Tran et Commit. Ils peuvent être utilisés séparément, mais les mêmes frais généraux de 14 octets par ligne sont établis.
Delux
merci d’avoir ajouté les détails supplémentaires sur la surcharge de 14 octets en cours d’établissement. Kim le passe en revue dans la vidéo, mais il est très utile de l'avoir également dans le texte.
Ali Razeghi
15

OK, rentra chez moi et testé. Voici l'observation.

CREATE DATABASE TEST;
GO
CREATE TABLE TABLE1
(
    ID tinyint,
    Details varchar(10)
);
GO
INSERT INTO TABLE1
VALUES (1, 'Original');
GO

SELECT
    name,
    snapshot_isolation_state_desc,
    is_read_committed_snapshot_on
FROM sys.databases
WHERE name = 'TEST';
GO

Premier test avec confirmation des deux paramètres sur OFF.

Requête 1

USE TEST;

BEGIN TRAN
UPDATE TABLE1
SET Details = 'Update'
WHERE ID = 1;

--COMMIT;
--ROLLBACK;
GO

Requête 2

USE TEST;

SELECT ID, Details
FROM TABLE1
WHERE ID = 1;
GO

Dans ce test, la requête 2 attend que la requête 1 soit validée, dm_tran_locks DMV montre ce verrouillage exclusif sur TABLE1 engagé par la requête 1.

USE TEST;

SELECT
    DB_NAME(tl.resource_database_id) AS DBName,
    resource_type,
    OBJECT_NAME(resource_associated_entity_id) AS tbl_name,
    request_mode,
    request_status,
    request_session_id
FROM sys.dm_tran_locks tl
WHERE 
    resource_database_id = db_id('TEST')
    AND resource_type = 'OBJECT'

Deuxième test , annuler la transaction précédente, définissez READ_COMMITTED_SNAPSHOT sur ON, mais laissez ALLOW_SNAPSHOT_ISOLATION sur OFF.

ALTER DATABASE TEST
SET READ_COMMITTED_SNAPSHOT ON
WITH ROLLBACK IMMEDIATE;
GO

Exécuter la requête 1, puis la requête 2. DMV indique que la requête 1 est soumise à un verrou exclusif, mais que la requête 2 renvoie les détails avec "Original" sans que la requête 1 valide la transaction. Il semble que la gestion des versions de ligne READ_COMMITTED est en place.

L'ajout SET TRANSACTION ISOLATION LEVEL SNAPSHOT;aux requêtes 1 et 2 et l'exécution de la requête 1 ou de la requête 2 renvoie une erreur. La transaction d'isolation de capture instantanée n'a pas pu accéder à la base de données 'TEST' car l'isolation de capture instantanée n'est pas autorisée dans cette base de données. Utilisez ALTER DATABASE pour autoriser l'isolation de cliché.

Troisième test , annuler la transaction précédente. Définissez READ_COMMITTED_SNAPSHOT OFF et ALLOW_SNAPSHOT_ISOLATION ON.

ALTER DATABASE TEST
SET READ_COMMITTED_SNAPSHOT OFF
WITH ROLLBACK IMMEDIATE;
GO

ALTER DATABASE TEST
SET ALLOW_SNAPSHOT_ISOLATION ON;
GO

Exécutez la requête 1, puis la requête 2. DMV indique le verrou exclusif généré par la requête 1. La requête 2 semble attendre que la requête 1 soit terminée. L'activation de ALLOW_SNAPSHOT_ISOLATION ne semble pas activer le contrôle de version des lignes READ COMMITTED.

Ajout SET TRANSACTION ISOLATION LEVEL SNAPSHOT;à la fois à la requête 1 et à la requête 2. Exécutez la requête 1, puis la requête 2. Tandis que DMV indique que la requête 1 a un verrou exclusif, la requête 2 renvoie les détails avec le mot 'Original'. L'isolation de l'instantané semble être en place.

L'observation du test montre qu'elle READ_COMMITTED_SNAPSHOTactive / désactive elle - même le contrôle de version des lignes READ COMMITTED, quel que soit le ALLOW_SNAPSHOT_ISOLATIONparamètre défini, et inversement.

Travis
la source
4

Votre compréhension est correcte. J'aime la définition courte, propre et simple d' ici :

Lorsque l'option de base de données READ_COMMITTED_SNAPSHOT est activée, les transactions définissant le niveau d'isolation validé en lecture utilisent le contrôle de version des lignes.

Lorsque l'option de base de données ALLOW_SNAPSHOT_ISOLATION est activée, les transactions peuvent définir le niveau d'isolation de capture instantanée.

Il semble que beaucoup de malentendus viennent de la SEP elle-même. Par exemple, ici ils disent:

Si vous définissez l'option de base de données READ_COMMITTED_SNAPSHOT sur ON, le moteur de base de données utilise la version des lignes et l'isolation de capture instantanée par défaut, au lieu d'utiliser des verrous pour protéger les données.

Mais "l'isolement instantané" mentionné n'est pas égal au comportement de transaction pour lequel set transaction isolation level snapshotest appliqué.

En ce qui concerne la différence, une bonne explication est ici .

Il serait probablement préférable que READ_COMMITTED_SNAPSHOT porte le nom READ_COMMITTED_ROW_VERSIONING ou quelque chose du genre. :)

ov
la source
0

J'aime ce résumé de Microsoft :

La définition de l'option READ_COMMITTED_SNAPSHOT ON permet d'accéder aux lignes versionnées sous le niveau d'isolement READ COMMITTED par défaut. Si l'option READ_COMMITTED_SNAPSHOT est définie sur OFF, vous devez définir explicitement le niveau d'isolation de capture instantanée pour chaque session afin d'accéder aux lignes versionnées.

flam3
la source