2011-01-07 9 views
10

Có lẽ tôi đang hiểu lầm gì đó về giao dịch hoặc những gì SQL Server đang làm nhưng xem xét các T-SQL sau:Làm cách nào để bỏ đặt/đặt lại mức cô lập giao dịch cho 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? 

Có lẽ nó không quan trọng, nhưng tôi thích cảm giác ấm áp mờ rằng tôi rời mọi thứ theo cách họ đã từng làm tôi đang làm. Có thể đặt lại mức cách ly về trạng thái ban đầu bất kể trạng thái trước đó là gì không?

Trả lời

12

Nếu mã của bạn được thực hiện bên trong một thủ tục lưu trữ, sự thay đổi này chỉ áp dụng trong phạm vi của proc lưu trữ - khi trở về proc lưu trữ, mức độ cô lập cho kết nối sẽ tự động chuyển sang chế độ trình độ theo thời gian:

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 

(Bỏ qua tập hợp kết quả từ sys.objects, kết quả đầu ra 2, 4 và 2 này là mức cách ly).

+0

Mã của tôi đã kết thúc trong một thư mục lưu trữ để có thể biết được điều đó. Cảm ơn! – DJTripleThreat

+0

@Damien_The_Unbeliever Điều này cũng áp dụng cho trình kích hoạt không? –

+0

@SpongebobComrade - vâng - ['ĐẶT GIAO DIỆN CẤP GIAO DỊCH '] (https://msdn.microsoft.com/en-GB/library/ms173763.aspx):" Nếu bạn phát hành CÀI ĐẶT GIAO DIỆN GIAO DỊCH SET trong một thủ tục hoặc kích hoạt được lưu trữ , khi đối tượng trả về điều khiển, mức cô lập được đặt lại về mức có hiệu lực khi đối tượng được gọi " –

14

Bạn biết mức hiện tại từ sys.dm_exec_sessions.transaction_isolation_level

Nếu bạn cần để span lô, sau đó sử dụng SET CONTEXT_INFO để bảo tồn giá trị mà cũng có thể được đọc từ sys.dm_exec_sessions sau này.

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. Thats thực sự hữu ích! Cảm ơn bạn đã đăng bài đó. – DJTripleThreat

1

Giải pháp GBNs không hoạt động đối với tôi. Tôi nghi ngờ nó sẽ hoạt động ở nơi khác.

Vấn đề là việc trở về mức cô lập trước đó chỉ hợp lệ trong ngữ cảnh của EXEC. Kịch bản của tôi là dưới đây. Lưu ý rằng nó cũng không cố gắng thay đổi cách ly nếu cách ly hiện tại bao gồm ảnh chụp nhanh. (Nó sẽ thất bại nếu bạn thử).

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;