2011-01-07 12 views
10

Może jestem rozumieją coś o transakcjach lub SQL Server, co robi, ale rozważmy następujący T-SQL:Jak usunąć/zresetować poziom izolacji transakcji dla SQL Server?

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; 
GO 

BEGIN TRANSACTION 

-- DO SOME READS AND OTHER THINGS 

COMMIT 

-- OK, WHAT HAPPENS TO THE ISOLATION LEVEL AFTER THIS? 

Może to nie ma znaczenia, ale podoba mi się mgliste ciepłe uczucie, że wyjeżdżam tak jak kiedyś, kiedy skończyłem robić to, co robię. Czy można przywrócić poziom izolacji do pierwotnego stanu, niezależnie od tego, jaki był stan wcześniej?

Odpowiedz

12

Jeśli kod jest wykonywany wewnątrz procedury przechowywanej, zmiana ma zastosowanie tylko w zakresie przechowywanej proc - gdy przechowywane powróci proc, poziom izolacji do połączenia automatycznie powróci do swojego poprzedniego poziomu:

create procedure dbo.IsoTest 
as 
    set transaction isolation level serializable 
    begin transaction 

    select transaction_isolation_level FROM sys.dm_exec_sessions where session_id = @@SPID 

    select object_id from sys.objects 

    commit 
go 
select transaction_isolation_level FROM sys.dm_exec_sessions where session_id = @@SPID 
exec dbo.IsoTest 
select transaction_isolation_level FROM sys.dm_exec_sessions where session_id = @@SPID 

(Ignorowanie zestawu wyników z sys.objects, to powoduje, że 2, 4 i 2 są poziomami izolacji).

+0

Mój kod zakończył się procesem przechowywanym, więc dobrze wiedzieć. Dzięki! – DJTripleThreat

+0

@Damien_The_Unbeliever Czy dotyczy to również wyzwalaczy? –

+0

@SpongebobComrade - tak - ["USTAWIĆ POZIOM IZOLACJI TRANSAKCJI"] (https://msdn.microsoft.com/en-GB/library/ms173763.aspx): "Jeśli wydasz SET TRANSACTION ISOLATION LEVEL w procedurze przechowywanej lub wyzwalaczu , gdy obiekt wraca do kontroli, poziom izolacji jest resetowany do poziomu obowiązującego, gdy obiekt został wywołany " –

14

Wiesz aktualny poziom od sys.dm_exec_sessions.transaction_isolation_level

Jeśli trzeba rozciągać partii, a następnie użyć SET CONTEXT_INFO aby zachować wartość, którą można również odczytać z sys.dm_exec_sessions później.

DECLARE @CurrentIsolationLevel smallint 

SELECT @CurrentIsolationLevel = transaction_isolation_level 
FROM sys.dm_exec_sessions 
WHERE session_id = @@SPID 

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; 
BEGIN TRANSACTION 
-- DO SOME READS AND OTHER THINGS 
COMMIT 

DECLARE @SQL varchar(200) 
SELECT @SQL = 'SET TRANSACTION ISOLATION LEVEL ' + 
     CASE @CurrentIsolationLevel 
      WHEN 1 THEN 'READ UNCOMMITTED' 
      WHEN 2 THEN 'READ COMMITTED' 
      WHEN 3 THEN 'REPEATABLE READ' 
      WHEN 4 THEN 'SERIALIZABLE' 
      WHEN 5 THEN 'SNAPSHOT' 
     END 
EXEC (@sql) 
+0

+1. To naprawdę przydatne! Dzięki za zamieszczenie tego. – DJTripleThreat

1

Rozwiązanie GBN nie działa dla mnie. Wątpię, żeby zadziałało gdzie indziej.

Problem polega na tym, że powrót do poprzedniego poziomu izolacji jest ważny tylko w kontekście EXEC. Mój skrypt znajduje się poniżej. Zauważ, że nie próbuje także zmienić izolacji, jeśli aktualna izolacja zawiera migawki. (Nie uda się, jeśli spróbujesz).

DECLARE @initalIsoloationLevel nvarchar(25) 

SELECT @initalIsoloationLevel = 
     CASE 
      WHEN transaction_isolation_level = 1 
      THEN 'READ UNCOMMITTED' 
      WHEN transaction_isolation_level = 2 
       AND is_read_committed_snapshot_on = 1 
      THEN 'READ COMMITTED SNAPSHOT' 
      WHEN transaction_isolation_level = 2 
       AND is_read_committed_snapshot_on = 0 
      THEN 'READ COMMITTED' 
      WHEN transaction_isolation_level = 3 
      THEN 'REPEATABLE READ' 
      WHEN transaction_isolation_level = 4 
      THEN 'SERIALIZABLE' 
      WHEN transaction_isolation_level = 5 
      THEN 'SNAPSHOT' 
      ELSE NULL 
     END 
FROM sys.dm_exec_sessions AS s 
WHERE session_id = @@SPID 

    /* Changing isolation level is not supported with snapshots */ 
IF @initalIsoloationLevel NOT LIKE '%SNAP%' AND @initalIsoloationLevel is NOT NULL 
    SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; 


/****** DO YOUR STUFF HERE ******/ 


    /* Changing isolation level is not supported with snapshots */ 
IF @initalIsoloationLevel = 'READ COMMITTED' 
    SET TRANSACTION ISOLATION LEVEL READ COMMITTED; 
ELSE IF @initalIsoloationLevel = 'REPEATABLE READ' 
    SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; 
ELSE IF @initalIsoloationLevel = 'SERIALIZABLE' 
    SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; 
Powiązane problemy