15

也许我对事务或 SQL Server 正在做什么有误解,但请考虑以下 T-SQL:

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
GO

BEGIN TRANSACTION

-- DO SOME READS AND OTHER THINGS

COMMIT

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

也许这无关紧要,但我喜欢那种温暖而模糊的感觉,一旦我完成了我正在做的事情,我就会让事情保持原样。无论之前的状态如何,是否可以将隔离级别重置回原始状态?

4

3 回答 3

18

如果您的代码在存储过程中执行,则更改仅适用于存储过程的范围内 - 当存储过程返回时,连接的隔离级别将自动恢复到之前的级别:

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 作为隔离级别)。

于 2011-01-08T11:58:29.287 回答
15

你知道当前的水平从sys.dm_exec_sessions.transaction_isolation_level

如果您需要跨批次,则使用SET CONTEXT_INFO来保留稍后也可以从 sys.dm_exec_sessions 读取的值。

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)
于 2011-01-08T10:25:56.720 回答
2

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;
于 2016-10-26T19:30:36.873 回答