Как отключить /reset уровень изоляции транзакций для SQL Server?
Возможно, я неправильно понимаю что-то о транзакциях или о том, что делает 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?
Возможно, это не имеет значения, но мне нравится теплое нечеткое ощущение, что я оставляю вещи так, как они были, когда я закончил делать то, что делаю. Возможно ли reset уровень изоляции вернуться в исходное состояние независимо от того, что было раньше?
Ответы
Ответ 1
Если ваш код выполняется внутри хранимой процедуры, изменение применяется только в области хранимой процедуры - при восстановлении сохраненного proc уровень изоляции для соединения автоматически вернется к нему на предыдущем уровне:
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 в качестве уровней изоляции).
Ответ 2
Вы знаете текущий уровень от 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)
Ответ 3
Решение GBNs для меня не работает. Я сомневаюсь, что он будет работать в другом месте.
Проблема заключается в том, что возврат к предыдущему уровню изоляции действителен только в контексте EXEC. Мой script приведен ниже. Обратите внимание, что он также не пытается изменить изоляцию, если текущая изоляция включает моментальные снимки. (Если вы попробуете, он потерпит неудачу).
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;