2011-01-07 11 views
10

たぶん私は、トランザクションについて何かを誤解したりサーバーが何をしているかをSQLが、次のT-SQLを考えてみます。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? 

たぶん、それは問題ではありませんが、私は私を残して、暖かいファジーな感じが好き物事は私がやっていることをやってやったと同じように。以前の状態に関係なく、分離レベルを元の状態に戻すことは可能ですか?

答えて

12

あなたのコードは、ストアドプロシージャ内で実行されている場合は、変更は唯一のストアドプロシージャの範囲の間に適用される - ストアドプロシージャ戻り、接続のための分離レベルが自動的にそれの前のレベルに戻りますが:

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 

(sys.objectsの結果セットを無視すると、分離レベルとして2,4および2が出力されます)。

+0

私のコードはストアドプロシージャで終わってしまいました。ありがとう! – DJTripleThreat

+0

@Damien_The_Unbelieverこれはトリガーにも適用されますか? –

+0

@SpongebobComrade - はい - [ 'SET TRANSACTION分離LEVEL'](https://msdn.microsoft.com/en-GB/library/ms173763.aspx):「あなたは、ストアドプロシージャまたはトリガに設定されたトランザクション分離レベルを発行する場合オブジェクトが制御を戻すと、オブジェクトが呼び出されたときに分離レベルがそのレベルにリセットされます。 " –

14

あなたはまた後でsys.dm_exec_sessionsから読み取ることができる価値を維持するためにSET CONTEXT_INFOを使用し、その後、バッチをスパンする必要がある場合は、sys.dm_exec_sessions.transaction_isolation_level

から現在のレベルを知っています。

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。それは本当に便利です!投稿していただきありがとうございます。 – DJTripleThreat

1

GBNsソリューションは、私のために動作しません。私はそれが他の場所ではうまくいかないと思う。

問題は、以前の分離レベルへの復帰は、EXECのコンテキスト内でのみ有効であるということです。私のスクリプトは以下の通りです。現在の隔離にスナップショットが含まれている場合は、隔離も変更されません。 (試してみると失敗します)。

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; 
関連する問題