SQL 中为什么经常要加Nolock?

运维 数据库运维
刚开始工作的时候,经常听同事说在SQL代码的表后面加上WITH(NOLOCK)会好一些,后来仔细研究测试了一下,终于知道为什么了。

[[423680]]

刚开始工作的时候,经常听同事说在SQL代码的表后面加上WITH(NOLOCK)会好一些,后来仔细研究测试了一下,终于知道为什么了。

那么加与不加到底有什么区别呢?

SQL在每次新建一个查询,就相当于创建了一个会话。在不同的查询窗口操作,会影响到其他会话的查询。当某张表正在写数据时,这时候去查询很可能就会一直处于阻塞状态,哪怕你只是一个很简单的SELECT也会一直等待。

我们这里使用事务来往某张表里写数据,我们知道事务在写完表必须提交(COMMIT)或回滚(ROLLBACK)才能释放表,否则会一直处于阻塞状态。

在插入过程中,我们写一个简单的查询语句,在不添加WITH(NOLOCK)和添加WITH(NOLOCK)的情况下,看会发生什么。

示例数据

如下表A,是我们新建的一个非常简单的表。

下面我们创建一个往里面写数据的事务(使用BEGIN TRAN就可以开始一个事务了)

我们发现有1行受影响了,注意这里的会话ID是59(左上角黄色标签上的数字)

不添加NOLOCK

我们新建一个查询窗口,然后查询A表

从上面的查询可以看到,表A被锁住了,我们的查询一直处于阻塞状态。这里的会话ID是60

这个时候如果你在会话59的窗口执行COMMIT或ROLLBACK,会话60的查询结果会立刻显示出来,这里为了下面的演示我们暂时不提交或回滚。

添加NOLOCK

我们再新建一个查询窗口,还是查询A表,这次我们加上NOLOCK。

注意上图标红色的地方,当前会话ID是55,旁边的60还在执行状态,而我们加了NOLOCK后,瞬间就查询出结果了,而且还把事务里即将要插入的数据给查询到了。这是为什么呢?

事务里的数据虽然还没有提交,但是它实际上已经存在内存里面了,这个时候我们使用NOLOCK查询到的结果,实际上还没存储到硬盘。

从上面的两个测试可以看出,NOLOCK的作用其实就是为了防止查询时被阻塞,只是这样会产生脏读(未提交的数据)。

那么一般什么情况下使用NOLOCK呢?

通常是一些被频繁写的表,不管是插入,更新还是删除。这样的表在查询时,使用NOLOCK是非常有效的。

WITH(NOLOCK)和NOLOCK的区别

不知道小伙伴注意没,我前面介绍时是写的WITH(NOLOCK),但是测试时,使用的是(NOLOCK),它们有什么区别呢?

为了搞清楚WITH(NOLOCK)与NOLOCK的区别,我们先看看下面三个SQL语句有啥区别

  1. SELECT * FROM A NOLOCK 
  2. SELECT * FROM A (NOLOCK); 
  3. SELECT * FROM A WITH(NOLOCK); 
  • (NOLOCK)这样的写法,NOLOCK其实只是别名的作用,而没有任何实质作用。所以不要粗心将(NOLOCK)写成NOLOCK
  • (NOLOCK)与WITH(NOLOCK)其实功能上是一样的。(NOLOCK)只是WITH(NOLOCK)的别名,但是在SQL Server 2008及以后版本中,(NOLOCK)不推荐使用了,"不借助 WITH 关键字指定表提示”的写法已经过时了。
  • 在使用链接服务器的SQL当中,(NOLOCK)不会生效,WITH(NOLOCK)才会生效。
  1. --这样会提示用错误 
  2. select * from [IP].[dbname].dbo.tableName with (nolock) 
  3. --这样就可以 
  4. select * from [dbname].dbo.tableName with(nolock) 

 

责任编辑:武晓燕 来源: SQL数据库开发
相关推荐

2022-11-15 08:35:00

SQLNOLOCK数据

2023-04-06 08:43:29

SQLWITH(NOLOCK

2022-06-09 08:32:21

SQLNOLOCKWITH

2020-06-16 08:17:11

代码空格开发

2022-07-01 08:35:50

keyReact前端

2017-03-24 16:39:57

2019-08-28 16:38:49

finalJava编程语言

2011-08-01 14:33:44

SQL

2013-03-12 14:30:09

Ubuntu操作系统

2021-10-13 06:49:13

SQL Server优化

2015-08-06 10:14:15

造轮子facebook

2022-08-15 08:27:02

基站网络

2018-05-23 00:20:29

2019-09-30 07:50:51

ITOps云端ITOM

2017-04-05 18:10:05

R语言开发Ross

2009-12-17 15:18:47

2012-06-18 14:51:09

Python

2022-03-30 08:21:57

合并HTTP

2021-03-16 08:35:14

Kubernetes Docker容器

2016-08-19 16:27:52

数据库Mongo DB开发
点赞
收藏

51CTO技术栈公众号