SET TRANSACTION ISOLATION LEVEL 仅适用于交易?

SET TRANSACTION ISOLATION LEVEL works only with transactions?

official example here 中,我们将 SET TRANSACTION ISOLATION LEVEL 与明确定义的事务结合使用。

我的问题是,如果我从 SqlCommand 执行查询,例如:

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SELECT * from MyTable

我会从我设置的新隔离级别中受益吗?

或者我是否需要明确定义这样的交易?

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
BEGIN TRANSACTION;
    SELECT * from MyTable
COMMIT TRANSACTION;

更新: 根据 ,我将更新我的查询如下:

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SELECT * from MyTable;
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;

这是为了克服possible isolation level leaks when using pooling.

第一个

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SELECT * from MyTable

会起作用。您设置的事务级别适用于每个后续事务,您的SELECT语句是其自身的隐式事务。

如果您需要确保多次读取过程中的某种程度的一致性,您只需要显式启动一个事务。例如,如果您使用 SERIALIZABLE,那么您可以将多个 SELECT 包装在一个事务中,并确保在您读取它时不修改基础数据。

SQL 服务器中的每个语句在事务上下文中都是 运行。当你做类似

的事情时
select * from [dbo].[foobar];

SQL 服务器确实如此:

begin transaction;
select * from [dbo].[foobar];
commit;

因此,设置明确的事务隔离级别确实会影响事务。甚至是数据库引擎代表您启动的隐含的!

是的,即使不在显式 BEGIN TRANSACTION 内,您也会受益于您设置的事务隔离级别。当您设置事务隔离级别时,它是在连接级别上设置的。

来自SET TRANSACTION ISOLATION LEVEL (Transact-SQL)

Only one of the isolation level options can be set at a time, and it remains set for that connection until it is explicitly changed.

可能发生的一个 "gotcha"(问题)是使用池时隔离级别可能会在不同连接之间泄漏。如果您在一个(或某些)特定代码段中显式设置隔离级别(但在大多数其他地方使用默认设置)并且还使用连接池。如果代码期望默认隔离级别 "A" 但获得了隔离级别显式设置为 "B" 的连接,这可能会导致奇怪的问题。

看来这个问题现在已在 SQL 服务器的更高版本中修复:SQL Server: Isolation level leaks across pooled connections