ALLOW_SNAPSHOT_ISOLATION y READ_COMMITTED_SNAPSHOT

38

La mayoría de los foros y ejemplos en línea siempre sugieren tener ambos ALLOW_SNAPSHOT_ISOLATIONy READ_COMMITTED_SNAPSHOTactivarlos siempre que alguien haga una instantánea, versiones de fila o preguntas similares.

Supongo que la palabra INSTANTÁNEA en ambos entornos se vuelve un poco confusa. Pensé que, para que el motor de la base de datos use el control de versiones de fila en lugar de bloqueos para el comportamiento predeterminado READ_COMMITTED, la base de datos READ_COMMITTED_SNAPSHOTse establece en ON independientemente de qué ALLOW_SNAPSHOT_ISOLATIONconfiguración.

La ALLOW_SNAPSHOT_ISOLATIONconfiguración se establece en ON solo para permitir el aislamiento de instantáneas al iniciar una transacción (por ejemplo, CONFIGURAR EL INSTANTÁNEA DEL NIVEL DE AISLAMIENTO DE LA TRANSACCIÓN) independientemente de la READ_COMMITTED_SNAPSHOTconfiguración.

La única razón para tener estas dos configuraciones establecidas en ON es cuando necesita tener READ COMMITTED versioning de fila Y aislamiento de instantánea.

Mi pregunta es, ¿es mi comprensión incorrecta de alguna manera? ¿Y que estos dos ajustes tienen que estar siempre en ON juntos (especialmente para las versiones READ COMMITTED row)?

Travis
fuente

Respuestas:

25

Su comprensión es correcta. Se vuelve un poco confuso.

Kim Tripp (uno de los programadores de SQL Server y una parte integral de SQLSkills) repasa exactamente lo que usted indicó en los videos de MCM sobre el aislamiento de instantáneas . Avance rápido a 41:45 en el video para llegar a la parte donde ella responde su pregunta.

Si usa, ALLOW_SNAPSHOT_ISOLATIONasegúrese de usar SET TRANSACTION ISOLATION LEVEL SNAPSHOTsu código, de lo contrario no obtendrá ninguno de los beneficios.

Si configura SET READ_COMMITTED_SNAPSHOT ON, entonces no hay necesidad de modificar ningún código. MS SQL Server aplica automáticamente el aislamiento de instantáneas para esa tabla.

No he probado para ver qué sucede si solicita un nivel de aislamiento diferente en su código, sospecho que sobrescribirá esta opción, pero pruébelo primero.

Un vistazo rápido a la sobrecarga de rendimiento con el aislamiento de instantáneas.

Buen artículo sobre cómo el aislamiento de instantáneas puede cambiar el comportamiento esperado de su aplicación . Muestra ejemplos de cómo una declaración de actualización y una declaración de selección pueden devolver resultados totalmente diferentes e inesperados.

Ali Razeghi
fuente
Gracias por el enlace. Al igual que otros BOL, ella discutió estos dos ajustes de forma independiente y colectiva (ahí es donde se vuelve un poco confuso, o tal vez lo pienso demasiado). Tuve que probarlo para comprenderlo mejor.
Travis
44
Esta es una gran respuesta y solo me gustaría aclarar un par de puntos. Primero, si solo está escaneando el video, comience a las 23:18 y a las 41:45. El tiempo temprano agrega más detalles. Aunque Kim menciona una respuesta a la pregunta original, aún es necesario modificar el código si se usan ambos. Read_Committed_Snapshot es un aislamiento a nivel de declaración, en otras palabras, solo se aplica a la declaración que se está ejecutando actualmente. Allow_Snapshot_Isolation es un aislamiento a nivel de transacción, todo entre Begin Tran y Commit. Se pueden activar por separado, pero se establece la misma sobrecarga de 14 bytes por fila.
Delux
gracias por agregar los detalles adicionales sobre la sobrecarga de 14 bytes establecida. Kim lo analiza en el video, pero también es muy útil tenerlo aquí en texto.
Ali Razeghi
15

OK, volví a casa y probé. Aquí está la observación.

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

Primera prueba con ambas configuraciones confirmadas como OFF.

Consulta 1

USE TEST;

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

--COMMIT;
--ROLLBACK;
GO

Consulta 2

USE TEST;

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

En esta prueba, la consulta 2 está esperando que se confirme la consulta 1, dm_tran_locks El DMV muestra ese bloqueo exclusivo en la TABLA 1 incurrido por la consulta 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'

Segunda prueba , deshaga la transacción anterior, configure READ_COMMITTED_SNAPSHOT ON pero deje ALLOW_SNAPSHOT_ISOLATION OFF.

ALTER DATABASE TEST
SET READ_COMMITTED_SNAPSHOT ON
WITH ROLLBACK IMMEDIATE;
GO

Ejecute la consulta 1 y la consulta 2. El DMV muestra que la consulta 1 tiene un bloqueo exclusivo, pero la consulta 2 devuelve detalles con 'Original' sin que la consulta 1 confirme la transacción. Parece que la versión de la fila READ_COMMITTED está en su lugar.

Al agregar la SET TRANSACTION ISOLATION LEVEL SNAPSHOT;consulta 1 y la consulta 2, y ejecutar la consulta 1 o la consulta 2, se produce un error: la transacción de aislamiento de instantánea no pudo acceder a la base de datos 'TEST' porque el aislamiento de instantánea no está permitido en esta base de datos. Use ALTER DATABASE para permitir el aislamiento de instantáneas.

Tercera prueba , deshacer la transacción anterior. Establezca READ_COMMITTED_SNAPSHOT OFF y 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

Ejecute la consulta 1 y luego la consulta 2. El DMV muestra el bloqueo exclusivo incurrido por la consulta 1. La consulta 2 parece estar esperando que se complete la consulta 1. Activar ALLOW_SNAPSHOT_ISOLATION ON no parece habilitar READ COMMITTED row versioning.

Agregar SET TRANSACTION ISOLATION LEVEL SNAPSHOT;tanto a la consulta 1 como a la consulta 2. Ejecute la consulta 1 y luego la consulta 2. Mientras el DMV muestra que la consulta 1 tiene un bloqueo exclusivo, la consulta 2 devuelve detalles con 'Original'. El aislamiento de la instantánea parece estar en su lugar.

La observación de la prueba muestra que READ_COMMITTED_SNAPSHOTsí mismo habilita / deshabilita la versión READ COMMITTED de la fila independientemente de la ALLOW_SNAPSHOT_ISOLATIONconfiguración, y viceversa.

Travis
fuente
4

Su comprensión es correcta. Me gusta la definición corta, limpia y simple de aquí :

Cuando la opción de base de datos READ_COMMITTED_SNAPSHOT está activada, las transacciones que configuran el nivel de aislamiento de lectura confirmada utilizan el control de versiones de fila.

Cuando la opción de base de datos ALLOW_SNAPSHOT_ISOLATION está activada, las transacciones pueden establecer el nivel de aislamiento de la instantánea.

Parece que muchos malentendidos provienen de la propia EM. Por ejemplo, aquí dicen:

Si configura la opción de base de datos READ_COMMITTED_SNAPSHOT en ON, el motor de la base de datos usa el control de versiones de filas y el aislamiento de instantáneas como predeterminado, en lugar de usar bloqueos para proteger los datos.

Pero el "aislamiento de instantánea" mencionado no es igual al comportamiento de la transacción para la cual set transaction isolation level snapshotse aplica.

En cuanto a la diferencia, una buena explicación está aquí .

Probablemente sería mejor si READ_COMMITTED_SNAPSHOT se nombrara como READ_COMMITTED_ROW_VERSIONING o algo así. :)

ov
fuente
0

Me gusta este resumen de Microsoft :

Establecer la opción READ_COMMITTED_SNAPSHOT ON permite el acceso a filas versionadas bajo el nivel de aislamiento predeterminado READ COMMITTED. Si la opción READ_COMMITTED_SNAPSHOT está establecida en OFF, debe establecer explícitamente el nivel de aislamiento de Instantáneas para cada sesión para acceder a las filas versionadas.

flam3
fuente