Sql server 为什么要同时使用NOLOCK和NOWAIT?
一位同事编写了一个使用提示“with(NOLOCK,NOWAIT)”的查询 e、 g 假设: NOLOCK说“不要担心任何级别的锁,现在就读取数据” NOWAIT说“不要等待,如果表被锁定,只会出错”Sql server 为什么要同时使用NOLOCK和NOWAIT?,sql-server,tsql,Sql Server,Tsql,一位同事编写了一个使用提示“with(NOLOCK,NOWAIT)”的查询 e、 g 假设: NOLOCK说“不要担心任何级别的锁,现在就读取数据” NOWAIT说“不要等待,如果表被锁定,只会出错” 问题: 为什么两者同时使用?当然NOWAIT永远不会实现,因为NOLOCK意味着它无论如何都不会等待锁定 NOLOCK与READUNCOMMITTED相同,其中: 。。。其他事务设置的独占锁不会阻止当前事务 从读取锁定的数据中删除事务 基于这句话,我想说您是正确的,发出NOLOCK实际上意味
问题:
为什么两者同时使用?当然NOWAIT永远不会实现,因为NOLOCK意味着它无论如何都不会等待锁定
NOLOCK
与READUNCOMMITTED
相同,其中:
。。。其他事务设置的独占锁不会阻止当前事务
从读取锁定的数据中删除事务
基于这句话,我想说您是正确的,发出NOLOCK
实际上意味着任何数据锁都是不相关的,因此NOWAIT
是多余的,因为查询不能被阻止
然而,文章接着说:
READUNCOMMITED和NOLOCK提示仅适用于数据锁
您还可以获得模式修改锁,NOLOCK
不能忽略这些锁。如果在更新架构对象时使用NOLOCK
发出查询,则您的查询可能会被Sch-M类型的锁阻止
看看在这种不太可能的情况下,NOWAIT
是否得到了尊重,这将是一件有趣的事情。然而,出于您的目的,我想它可能是多余的。它是多余的(或者至少是无效的)。在一个查询窗口中,执行:
create table T (ID int not null)
begin transaction
alter table T add ID2 int not null
保持此窗口打开,打开另一个查询窗口并执行:
select * from T WITH (NOLOCK,NOWAIT)
尽管有NOWAIT
提示,尽管有文档记录它在遇到任何锁时立即返回消息,但第二个查询将挂起,等待模式锁
阅读以下文档:
NOWAIT
:
指示数据库引擎在表上遇到锁时立即返回消息
请注意,这是关于锁,any锁
NOLOCK
(实际上是READUNCOMMITTED
):
READUNCOMMITTED和NOLOCK提示仅适用于数据锁。所有查询,包括带有READUNCOMMITTED和NOLOCK提示的查询,都会在编译和执行期间获取Sch-S(模式稳定性)锁。因此,当并发事务持有表上的Sch-M(模式修改)锁时,查询将被阻止
因此,NOLOCK
确实需要等待一些锁。
将它们一起使用没有任何意义。NOLOCK覆盖NOWAIT的行为。下面是NOWAIT功能的演示。在NOLOCK中进行注释,并观察记录返回,尽管存在独占锁定 创建表。在不提交事务的情况下执行第一个SSMS窗口。执行第二个窗口,由于没有等待而导致错误。注释掉第一个查询,并使用NOLOCK和NOWAIT执行第二个查询。得到结果。完成后回滚事务 DDL
USE [tempbackup]
GO
/****** Object: Table [TEST_TABLE] Script Date: 02/19/2014 09:14:00 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [TEST_TABLE](
[ID] [int] IDENTITY(1,1) NOT NULL,
[Name] [varchar](50) NULL,
CONSTRAINT [PK_TEST_TABLE] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
INSERT INTO tempbackup.dbo.TEST_TABLE(Name) VALUES ('MATT')
GO
SSMS窗口1
BEGIN TRANSACTION
UPDATE tempbackup.dbo.TEST_TABLE WITH(XLOCK) SET Name = 'RICHARD' WHERE ID = 1
--ROLLBACK TRANSACTION
SSMS窗口2
SELECT * FROM tempbackup.dbo.TEST_TABLE WITH(NOWAIT)
--SELECT * FROM tempbackup.dbo.TEST_TABLE WITH(NOLOCK,NOWAIT)
你为什么不试着用一些测试数据看看会发生什么?!已经这样做了,它立即返回-即NOLOCK won-我的问题是“为什么一起使用它们?是否存在NOLOCK不会赢的情况?”我想你是对的,
nowait
是多余的,但希望有人能以某种权威回答!刚刚做了测试NOWAIT
仍然会阻止等待模式锁定,因此它看起来毕竟是多余的。@Damien\u不相信者-它甚至无法编译查询并开始执行,因此提示永远不会真正进入其中<代码>设置锁定超时0;使用(NOLOCK)从T中选择*将是完成此操作的唯一方法。
SELECT * FROM tempbackup.dbo.TEST_TABLE WITH(NOWAIT)
--SELECT * FROM tempbackup.dbo.TEST_TABLE WITH(NOLOCK,NOWAIT)