具有设置事务隔离级别的更新语句读取未提交

BVe*_*non 8 sql-server locking

如果我有一个带有 的存储过程set transaction isolation level read uncommitted,它会影响更新语句吗?

我知道你不应该with (nolock)在更新/删除语句上使用,这几乎是一样的,但不确定 SQL 是否在过程中的更新语句上忽略它,或者如果有更新语句我应该小心不要使用它。

编辑:

对困惑感到抱歉。我不是想弄清楚在操作语句上使用这种类型的锁定会产生什么影响,或者这是否是一个好主意。事实上,我不想在操作语句上使用这种锁定,所以我的问题是将“设置事务...”放在我的存储过程的顶部是否会被更新/删除语句所尊重,或者它将被忽略。我希望它只是被忽略。

我完全了解它对 select 语句的影响(及其优点和缺点)。

Mar*_*ith 5

如果我有一个设置事务隔离级别读取未提交的存储过程,它会影响更新语句吗?

未提交读允许脏读。一个X锁将采取行或更高的水平(在数据页或索引),它是由脏了。在定位要更新的行时,查询直接访问的行将U被锁定并被阻塞。

但是,更新仍然有可能受到隔离级别的影响。

连接 1

CREATE TABLE T1
(
X INT NULL,
Y INT NULL
);

INSERT INTO T1 DEFAULT VALUES;

BEGIN TRAN
UPDATE T1 SET X = 100;    

WAITFOR DELAY '00:00:10'

ROLLBACK;
Run Code Online (Sandbox Code Playgroud)

连接 2(在触发连接 1 的 10 秒内运行此程序)

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

UPDATE T1
SET    Y = (SELECT SUM(X)
            FROM   T1);

SELECT *
FROM   T1; 
Run Code Online (Sandbox Code Playgroud)

结果

在此处输入图片说明

读取操作读取未提交的值,最终结果用于UPDATE即使100读取的最终回滚。


jya*_*yao 4

“事务隔离级别”主要影响(以我的理解)读操作的行为,即读操作是否会发出一些锁。对于“读未提交”的情况,这里引用MSDN

运行在 READ UNCOMMITTED 级别的事务不会发出共享锁来防止其他事务修改当前事务读取的数据。READ UNCOMMITTED 事务也不会被排它锁阻塞,排它锁会阻止当前事务读取已被其他事务修改但未提交的行

因此,对于您的问题,答案是否定的,更新不会受到同一存储过程内“读未提交”事务隔离级别的影响。

--更新(证明这个逻辑的示例)在SSMS中,我们打开两个窗口,并在窗口1(以下简称W1)中,运行以下命令

use tempdb
create table dbo.t (a int)
go
insert into dbo.t (a) values (10)
go
begin tran
update dbo.t 
set a = 20
where a = 10

-- commit tran
Run Code Online (Sandbox Code Playgroud)

在另一个窗口 (W2) 中,运行以下命令(请参阅行为注释)

use TempdB
set transaction isolation level read uncommitted
select * from dbo.t -- you can have dirty read, showing [a]=20, which is an uncommitted UPDATE in W1

go
-- the following update will wait (before proper locks are granted)
update dbo.t 
set a = 30
where a= 10
Run Code Online (Sandbox Code Playgroud)

这意味着 W2 中的 UPDATE 语句(带有 READ UNCOMMITTED)不会像 SELECT 语句一样受到事务隔离级别的影响(即仍然按预期运行)。

-- 更新 2:根据 MSDN更新t-sql,

与(表提示限制)

指定目标表允许的一个或多个表提示。需要WITH 关键字和括号。不允许使用NOLOCK 和 READUNCOMMITTED 。有关表提示的信息,请参阅表提示 (Transact-SQL)。

所以我的理解是,当你在SQL Server中运行UPDATE语句时,即使你可以在会话中读取脏数据,你也无法更新脏数据(即未提交的数据)。

  • 杰弗里 - 当我错了时,我不介意承认! (2认同)