web-dev-qa-db-fra.com

ALLOW_SNAPSHOT_ISOLATION et READ_COMMITTED_SNAPSHOT

La plupart des forums et des exemples en ligne suggèrent toujours d'avoir à la fois ALLOW_SNAPSHOT_ISOLATION et READ_COMMITTED_SNAPSHOT défini sur ON chaque fois que quelqu'un pose un instantané, une version de ligne ou une question similaire.

Je suppose que l'INSTANTANÉ de mots dans les deux paramètres devient un peu déroutant. Je pensais que, pour que le moteur de base de données utilise le versionnage des lignes au lieu des verrous pour le comportement par défaut de READ_COMMITTED, la base de données READ_COMMITTED_SNAPSHOT est réglé sur ON peu importe de ce que ALLOW_SNAPSHOT_ISOLATION réglage.

Le ALLOW_SNAPSHOT_ISOLATION le paramètre est défini sur ON uniquement pour permettre l'isolement des instantanés lors du démarrage d'une transaction (par exemple, INSTALANER LE NIVEAU D'ISOLEMENT DE TRANSACTION) peu importe of READ_COMMITTED_SNAPSHOT réglage.

La seule raison pour laquelle ces deux paramètres sont définis sur ON est le moment où il doit avoir la version en ligne de LECTURE COMMISE ET isolation de l'instantané.

Ma question est la suivante: ma compréhension est-elle incorrecte en quelque sorte? Et que ces deux paramètres doivent toujours être activés ensemble (en particulier pour le versioning de ligne LECTURE COMMISE)?

40
Travis

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

Kim Tripp (l'un des programmeurs de SQL Server et une partie intégrante de SQLSkills) passe exactement par ce que vous avez déclaré dans le Vidéos MCM sur l'isolement de l'instantané . Avance rapide à 41:45 dans la vidéo pour arriver à la partie où elle répond à votre question.

Si tu utilises ALLOW_SNAPSHOT_ISOLATION assurez-vous d'utiliser SET TRANSACTION ISOLATION LEVEL SNAPSHOT dans votre code, sinon vous ne bénéficierez d'aucun des avantages.

Si vous définissez SET READ_COMMITTED_SNAPSHOT ON, il n'est alors pas nécessaire de modifier de code. MS SQL Server applique automatiquement l'isolement 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 soupçonne qu'il écrasera cette option mais testez-le d'abord.

n aperçu rapide des frais généraux de performance à l'aide de l'isolement de capture instantanée.

Bon article sur la façon dont l'isolement de cliché peut changer le comportement attendu de votre application . Il montre des exemples de la façon dont une instruction update et une instruction select peuvent renvoyer des résultats totalement différents et inattendus.

26
Ali Razeghi

OK, je suis rentré chez moi et j'ai 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 les deux paramètres confirmés comme étant désactivés.

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 la validation de la requête 1, dm_tran_locks DMV montre ce verrou exclusif sur TABLE1 généré 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, annulez la transaction précédente, définissez READ_COMMITTED_SNAPSHOT ON mais laissez ALLOW_SNAPSHOT_ISOLATION OFF.

ALTER DATABASE TEST
SET READ_COMMITTED_SNAPSHOT ON
WITH ROLLBACK IMMEDIATE;
GO

Exécutez la requête 1 et exécutez la requête 2. DMV montre que la requête 1 comporte un verrou exclusif, mais la requête 2 renvoie des détails avec "Original" sans que la requête 1 valide la transaction. Il semble que le contrôle de version des lignes READ_COMMITTED soit en place.

Ajouter SET TRANSACTION ISOLATION LEVEL SNAPSHOT; sur la requête 1 et la requête 2, et exécuter la requête 1 ou la requête 2 renvoie une erreur - La transaction d'isolement de l'instantané n'a pas pu accéder à la base de données 'TEST' car l'isolement de l'instantané n'est pas autorisé dans cette base de données. Utilisez ALTER DATABASE pour permettre l'isolement de l'instantané.

Troisième test, annule la transaction précédente. Réglez 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 affiche le verrouillage exclusif généré par la requête 1. La requête 2 semble attendre la fin de la requête 1. L'activation de ALLOW_SNAPSHOT_ISOLATION ne semble pas activer le versioning de ligne READ COMMITTED.

Ajouter 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. Alors que DMV montre que la requête 1 comporte un verrou exclusif, la requête 2 renvoie les détails avec 'Original'. L'isolement de l'instantané semble être en place.

L'observation du test montre que READ_COMMITTED_SNAPSHOT lui-même active/désactive le versioning de la ligne LIRE COMMITTÉ indépendamment de ALLOW_SNAPSHOT_ISOLATION paramètre, et vice versa.

15
Travis

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

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

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

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 en ligne et l'isolement de l'instantané par défaut, au lieu d'utiliser des verrous pour protéger les données.

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

Quant à la différence, Nice explication est ici .

Il serait probablement préférable que READ_COMMITTED_SNAPSHOT soit nommé READ_COMMITTED_ROW_VERSIONING ou quelque chose du genre. :)

4
o.v

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'isolement de l'instantané pour chaque session afin d'accéder aux lignes versionnées.

0
flam3