事务隔离级别的范围

42

SQL Server 2005事务隔离级别的作用域规则是什么?我知道不同的级别意味着什么,但不知道如何在手动运行脚本之外正确地应用它们。我找不到一份适用于生产质量代码的实用指南。

显然,作用域从使用类似以下命令开始:

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED 

但是它会在哪里结束呢?如果我在存储过程中设置了ISO级别,然后该过程调用另一个过程,那么嵌套的过程是否继承它?更好的是,如果我在嵌套的过程中提升了ISO级别,它会传递回调用的过程吗?像BEGIN TRAN、ROLLBACK和COMMIT这样的事务命令是否有任何区别?

当应用程序或代理作业调用存储过程时,隔离级别更改是否以某种方式持久化?我总是需要在每个过程结束时恢复默认的READ COMMITTED吗?

我想在不同情况下进行测试,但我不知道如何读取当前隔离级别被设置为什么。


这个事实超出了当前事务的范围(并且由于连接池,超出了当前“会话”),可能会让你陷入困境。请参阅我在此主题上撰写的这篇文章 - ChaseMedallion
6个回答

37

运行以下代码,自己查看结果:

CREATE PROCEDURE dbo.KeepsIsolation
AS
BEGIN
PRINT 'Inside sproc that does not change isolation level';
DBCC USEROPTIONS;
END
GO

CREATE PROCEDURE dbo.ChangesIsolation
AS
BEGIN
PRINT 'Inside sproc that changes isolation level';
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
DBCC USEROPTIONS;
END
GO
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
DBCC USEROPTIONS;
EXEC dbo.KeepsIsolation;
DBCC USEROPTIONS;
EXEC dbo.ChangesIsolation;
-- demonstrates that isolation level restored to REPEATABLE READ after exiting the procedure
    DBCC USEROPTIONS;

16
看起来父进程不会受到子进程内的ISO级别更改的影响,但子进程会将父进程的ISO级别作为默认值继承。 - SurroundedByFish

17

来自 MSDN

如果您在存储过程或触发器中使用 SET TRANSACTION ISOLATION LEVEL,当对象返回控制时,隔离级别将被重置为调用该对象时生效的那个级别。例如,如果您在批处理中设置了 REPEATABLE READ,而该批处理随后调用了一个将隔离级别设置为 SERIALIZABLE 的存储过程,则在存储过程将控制权返回给批处理时,隔离级别设置将恢复为 REPEATABLE READ。


15

DBCC USEROPTIONS 将显示当前的隔离级别,以及所有其他 SET 选项。


4

来自在线书籍

事务隔离级别选项只能设置一个, 并且它在连接中保持设置状态, 直到明确更改为止。除非在语句的FROM子句中指定了优化选项, 否则这将成为默认行为。


6
然而,被接受的答案表明这不是真的——在存储过程中更改隔离级别并不会更改调用存储过程的级别。要么文档有误,要么我理解错了。 - redcalx
1
同意之前的评论。虽然我欣赏引用 BOL 评论,但这似乎与被接受的答案不符。 - snth
2
实际上这是正确的。但它并不完整。如果你忽略文档中给出的异常(请查看Andrey的引用),那么这就是人们发布的糟糕答案的类型。 - TomTom

2

事务的隔离级别不会随着事务回滚而回滚。

即使您调用存储过程和函数,隔离级别也保持不变。


1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接