with(nolock)的用法

本文探讨了with(nolock)在SQL查询中的使用,强调了其用于优化性能但可能导致脏读的问题。介绍了脏读、不可重复读和幻读的概念,并说明了适用场景和限制,如大数据表、数据不常修改和特定业务逻辑。最后,对比了nolock与with(nolock)的区别,以及它们在不同环境下的使用技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

with(nolock)的用法

本文导读:要提升SQL的查询效能,一般来说大家会以建立索引(index)为第一考虑。其实除了index的建立之外,当我们在下SQL Command时,在语法中加一段WITH (NOLOCK)可以改善在线大量查询的环境中数据集被LOCK的现象藉此改善查询的效能。不过有一点千万要注意的就是,WITH (NOLOCK)的SQL SELECT有可能会造成Dirty Read。

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

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

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

一、with(nolock)的介绍

大家在写查询时,为了性能,往往会在表后面加一个nolock,或者是with(nolock),其目的就是查询是不锁定表,从而达到提高查询速度的目的。

当同一时间有多个用户访问同一资源,并发用户中如果有用户对资源做了修改,此时就会对其它用户产生某些不利的影响,例如:

1、脏读

一个用户对一个资源做了修改,此时另外一个用户正好读取了这条被修改的记录,然后,第一个用户放弃修改,数据回到修改之前,这两个不同的结果就是脏读。

2、不可重复读

一个用户的一个操作是一个事务,这个事务分两次读取同一条记录,如果第一次读取后,有另外用户修改了这个数据,然后第二次读取的数据正好是其它用户修改的数据,这样造成两次读取的记录不同,如果事务中锁定这条记录就可以避免。

3、幻读

指用户读取一批记录的情况,用户两次查询同一条件的一批记录,第一次查询后,有其它用户对这批数据做了修改,方法可能是修改,删除,新增,第二次查询时,会发现第一次查询的记录条目有的不在第二次查询结果中,或者是第二次查询的条目不在第一次查询的内容中。

NOLOCK 语句执行时不发出共享锁,允许脏读 ,等于 READ UNCOMMITTED事务隔离级别 。nolock确实在查询时能提高速度,但它并不是没有缺点的,起码它会引起脏读、只适用与select查询语句。 在一些不需要考虑脏读的场合会用到,例如当用户在论坛发广告贴时删除其所有发帖,这个查询就不怕脏读,全删,或者漏一个正在发的都不是问题。

二、实例

SQL 代码 复制

SELECT COUNT(UserID)

FROM EMPLOYEE WITH (NOLOCK)

JOIN WORKING_GROUP WITH (NOLOCK)

ON EMPLOYEE.UserID = WORKING_GROUP.UserID

三、with(nolock)的使用场景

1:数据量特别大的表,牺牲数据安全性来提升性能是可以考虑的;

2:允许出现脏读现象的业务逻辑,反之一些数据完整性要求比较严格的场景就不合适了,像金融方面等。

3:数据不经常修改的表,这样会省于锁定表的时间来大大加快查询速度。

4、当使用NoLock时,它允许阅读那些已经修改但是还没有交易完成的数据。因此如果有需要考虑transaction事务数据的实时完整性时,使用WITH (NOLOCK)就要好好考虑一下。

四、nolock和with(nolock)的几个小区别

1、SQL05中的同义词,只支持with(nolock);

2、with(nolock)的写法非常容易再指定索引。

3、跨服务器查询语句时 不能用with (nolock) 只能用nolock,同一个服务器查询时 则with(nolock)和nolock都可以用

SQL Server 中,`NOLOCK` 是一种查询提示(Table Hint),用于指示查询优化器在读取表时不需要获取共享锁或互斥锁,从而避免阻塞其他操作。这种行为允许查询在读取数据时不会因为其他事务未提交而被阻塞,同时也可以减少锁资源的占用,提升查询性能。然而,这种操作也可能导致读取到未提交的“脏”数据[^2]。 ### 使用方法 `NOLOCK` 查询提示通常以 `WITH(NOLOCK)` 的形式附加在表名之后,适用于 `SELECT` 语句。其基本语法如下: ```sql SELECT column1, column2 FROM table_name WITH(NOLOCK) WHERE condition; ``` 例如,假设有一个名为 `Employees` 的表,可以使用以下语句查询数据而不会受到锁的影响: ```sql SELECT Name, Department FROM Employees WITH(NOLOCK) WHERE Salary > 50000; ``` ### 注意事项 1. **脏读风险** 使用 `NOLOCK` 时,可能会读取到其他事务尚未提交的数据。如果这些数据随后被回滚,那么查询结果中将包含不存在的数据,这可能导致业务逻辑错误。 2. **数据一致性问题** 由于 `NOLOCK` 绕过了锁机制,因此可能会导致查询结果中出现重复记录或遗漏记录的情况,尤其是在数据频繁更新的环境中。 3. **适用场景** `NOLOCK` 适用于对数据一致性要求不高的场景,例如报表生成、数据分析等,而不建议在需要高精度和一致性的事务处理中使用。 4. **性能影响** 虽然 `NOLOCK` 可以减少锁争用并提高查询性能,但在某些情况下,它可能导致查询计划的变化,从而影响性能。 5. **索引使用** 如果表具有非聚集索引,并且希望在使用 `NOLOCK` 时指定索引,可以使用 `WITH(NOLOCK, INDEX(index_name))` 的形式[^1]。 6. **与事务隔离级别的关系** `NOLOCK` 实际上等同于 `READ UNCOMMITTED` 隔离级别。因此,在使用 `NOLOCK` 时,应确保理解当前数据库的事务隔离级别及其对查询行为的影响。 ### 示例:结合索引提示使用 NOLOCK ```sql SELECT Name, Department FROM Employees WITH(NOLOCK, INDEX(IX_Employees_Department)) WHERE Department = 'HR'; ``` 上述语句将强制查询使用名为 `IX_Employees_Department` 的索引,并且不会阻塞其他事务。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值