SQL Server中嵌套事务的隔离范围是什么?

8
考虑以下SQL:
BEGIN TRAN
SET TRANSACTION ISOLATION LEVEL READ COMMITTED
INSERT Bands ( Name ) SELECT 'Depeche Mode' UNION SELECT 'Arcade Fire'
-- 我已经缩进了内部的事务,以使它更清晰。
BEGIN TRAN SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
SELECT * FROM Bands
COMMIT
-- 这里的隔离级别是什么?
UPDATE Bands SET Name = 'Modest Mouse' WHERE Name = 'Oddest House'
COMMIT
总之,我们开始一个事务并将其隔离级别设置为READ COMMITTED。然后我们执行一些随机的SQL语句并开始另一个嵌套事务。在此事务中,我们将隔离级别更改为READ UNCOMMITTED。然后我们提交该事务并返回到其他事务。
现在,我猜测在内部提交后,隔离级别会返回到READ COMMITTED。这正确吗?
2个回答

11

你 [Bob Probst] 是正确的。有趣的是,根据你链接的文档

如果您在存储过程或触发器中发出 SET TRANSACTION ISOLATION LEVEL 命令,则当对象返回控件时,隔离级别将重新设置为调用该对象时有效的级别。例如,如果您在批处理中设置了 REPEATABLE READ,然后该批处理调用了一个将隔离级别设置为 SERIALIZABLE 的存储过程,则当存储过程返回控件到批处理时,隔离级别设置将恢复为 REPEATABLE READ。

因此,这里的关键问题是 SET TRANSACTION ISOLATION LEVEL 具有程序亲和性而不是事务亲和性(我之前认为有事务亲和性)。

太棒了!


2
好吧,真糟糕,哈哈!我的C#数据库API倾向于接受开放连接对象,以便我可以调用多个函数而不必每次都打开新连接。这种缺乏“事务关联”意味着如果我从另一个数据库API方法中调用一个数据库API方法,并且两者都使用事务,则嵌套的事务可能会改变调用方事务的事务隔离级别。肯定很糟糕。解决方法是......对于任何使用事务的C#方法,请使用C#代码模拟C#事务的过程关联,通过保存隔离级别(dbcc useroptions)并在返回之前将其恢复! - Triynko
这个"anwer"本应该是一条评论。但请原谅,那是2008年的事情。:) - Gregory Higley

8
我不认为那是正确的。
请参考此处的备注:设置事务

一次只能设置一个隔离级别选项,并且它将保持在该连接中,直到明确更改。


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