2008-10-21 21 views
6

Consideremos el siguiente código SQL:¿Cuál es el alcance del aislamiento en las transacciones anidadas en SQL Server?

 
BEGIN TRAN 
SET TRANSACTION ISOLATION LEVEL READ COMMITTED 

INSERT Bands 
    ( Name ) 
SELECT 'Depeche Mode' 
UNION 
SELECT 'Arcade Fire' 

    -- I've indented the inner transaction to make it clearer. 

    BEGIN TRAN 
    SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED 

    SELECT * 
     FROM Bands 

    COMMIT 

-- What is the isolation level right here? 

UPDATE Bands 
    SET Name = 'Modest Mouse' 
WHERE Name = 'Oddest House' 

COMMIT 

En suma, iniciar una transacción y establecer su nivel de aislamiento a READ COMMITTED. Luego hacemos SQL aleatorio y comenzamos otra transacción anidada. En esta transacción, cambiamos el nivel de aislamiento a READ UNCOMMITTED. Luego cometemos esa transacción y volvemos a la otra.

Ahora, supongo que después del compromiso interno, el nivel de aislamiento vuelve a READ COMMITTED. ¿Es esto correcto?

Respuesta

7

No creo que sea correcto.

Consulte las observaciones aquí: Set Transaction

Sólo uno de los niveles de aislamiento opciones se pueden establecer a la vez, y permanece fijado a tal conexión hasta se cambia de forma explícita.

+0

esto es correcto, acabo de probar con sp_lock –

7

Usted [Bob Probst] está en lo cierto. Curiosamente, según el documentation se conectó:

Si emite conjunto de transacciones AISLAMIENTO DE NIVEL en un procedimiento almacenado o disparador, cuando el objeto se devuelve el control del nivel de aislamiento se restablece al nivel vigente cuando se invoca el objeto. Por ejemplo, si configura REPEATABLE READ en un lote y el lote llama a un procedimiento almacenado que establece el nivel de aislamiento en SERIALIZABLE, la configuración del nivel de aislamiento vuelve a REPEATABLE READ cuando el procedimiento almacenado devuelve el control al lote.

Así, la línea de fondo aquí es que SET TRANSACTION ISOLATION LEVEL ha procedimiento afinidad, no afinidad transacción (como lo había pensado).

¡Impresionante!

+2

Bueno, eso es una mierda, ¡lol! Mi API de base de datos de C# tiende a aceptar objetos de conexión abiertos para que pueda llamar a varias funciones sin abrir una nueva conexión cada vez. Esta falta de "afinidad de transacción" significa que si llamo a un método de API de base de datos desde otro, y ambos utilizan una transacción, la transacción anidada podría alterar el nivel de aislamiento de transacción de la transacción de la persona que llama. Definitivamente apesta. SOLUCIÓN ... para cualquier método de C# que utilice una transacción, simule la afinidad de procedimiento para las transacciones de C# con el código C# guardando el nivel de aislamiento (usb dbcc) y restaurándolo antes de volver! – Triynko

+0

Este "anwer" debería haber sido un comentario. Pero dame un descanso. Fue en 2008. :) –

Cuestiones relacionadas