Sqlserver 中select with(nolock)等同于READUNCOMMITTED脏读的理解和实验

https://learn.microsoft.com/zh-cn/sql/t-sql/queries/hints-transact-sql-table?view=sql-server-ver16
https://learn.microsoft.com/en-us/sql/t-sql/queries/hints-transact-sql-table?view=sql-server-ver16
以上官方文档说NOLOCK 等效于 READUNCOMMITTED,不过我个人认为READUNCOMMITTED是针对整个会话而言,NOLOCK针对某表而言,就功能而言两者没有太大的区别

READUNCOMMITTED
指定允许脏读。 不发布共享锁来阻止其他事务修改当前事务读取的数据,其他事务设置的排他锁不会阻碍当前事务读取锁定数据。 允许脏读可能产生较多的并发操作,但其代价是读取以后会被其他事务回滚的数据修改。 这可能会使您的事务出错,向用户显示从未提交过的数据,或者导致用户两次看到记录(或根本看不到记录)。

READUNCOMMITTED 和 NOLOCK 提示仅适用于数据锁。 所有查询(包括那些带有 READUNCOMMITTED 和 NOLOCK 提示的查询)都会在编译和执行过程中获取 Sch-S(架构稳定性)锁。 因此,当并发事务持有表的 Sch-M(架构修改)锁时,将阻塞查询。 例如,数据定义语言 (DDL) 操作在修改表的架构信息之前获取 Sch-M 锁。 所有并发查询(包括那些使用 READUNCOMMITTED 或 NOLOCK 提示运行的查询)都会在尝试获取 Sch-S 锁时被阻塞。 相反,持有 Sch-S 锁的查询将阻塞尝试获取 Sch-M 锁的并发事务。

不能为通过插入、更新或删除操作修改过的表指定 READUNCOMMITTED 和 NOLOCK。 SQL Server 查询优化器忽略 FROM 子句中应用于 UPDATE 或 DELETE 语句的目标表的 READUNCOMMITTED 和 NOLOCK 提示。

备注:在 SQL Server 的未来版本中,将不再支持在 FROM 子句中使用应用于 UPDATE 或 DELETE 语句目标表的 READUNCOMMITTED 和 NOLOCK 提示。 请避免在新的开发工作上下文中使用这些提示,并计划修改当前使用它们的应用程序。

实验
会话1

CREATE TABLE testtable1 (h1 int,h2 char(200),h3 char(200))
begin transaction insert1
declare @i int 
set @i=1 
while @i<1000
begin
   insert into testtable1 (h1,h2,h3)
    values(@i,'hhhhhh2','hhhhhh3');
   set @i=@i+1;
   waitfor delay'00:00:01:00'
   end
commit transaction insert1

会话2

select count(*) from testtable1 with(nolock) 
GO
select count(*) from testtable1 

在会话1的事务提交之前,会话2执行几次的结果中,第一条命令select count() from testtable1 with(nolock)的结果会增加,比如10,11,12条记录这样子,但是select count() from testtable1的结果一直是0,说明with(nolock)确实读的是脏数据,如果会话2 with(nolock)给用户展示数据后,会话1回滚了,那么会话2 with(nolock)给用户展示的数据就是错误数据

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值